感謝KevinLu的回覆, 以下是我的步驟
我先在我的初始化那邊加入以下程式
#ifndef __MPLAB_DEBUGGER_SIMULATOR
while ((HLVDCON & _HLVDCON_BGVST_MASK) != (_HLVDCON_BGVST_MASK))
;
#endif
HLVDCONCLR = _HLVDCON_VDIR_MASK; // Event occurs when voltage equals or falls below trip point
HLVDCONSET = (0b0110) << _HLVDCON_HLVDL_POSITION; // 3.0V
HLVDCONCLR = _HLVDCON_SIDL_MASK;
HLVDCONSET = _HLVDCON_ON_MASK;
然後在interrupt.c那邊加入
void __attribute__((nomips16)) _nmi_handler(void) {
uint32_t getRNMICON = RNMICON;
SYSKEY = 0x00000000;
SYSKEY = 0xAA996655;
SYSKEY = 0x556699AA;
...
if ((getRNMICON & _RNMICON_HLVD_MASK) == _RNMICON_HLVD_MASK) {
// Programmable High/Low-Voltage Detect
EEPROM_WordWrite(0x700, 0x87);
char timestamp[16];
uart_buffer_t uartMessage = {};
formatString_Timestamp(timestamp);
sprintf(uartMessage.data, //
"rn%sRNMICON = 0x%08X;(%s:%d)rn", //
timestamp, //
RNMICON, //
__FILE__, //
__LINE__);
uartMessage.len = strlen(uartMessage.data);
UART_PushTxQueue(UART_6, &uartMessage);
RNMICONCLR = _RNMICON_HLVD_MASK;
}
...
SYSKEY = 0x33333333;
asm volatile("eret"); // return from interrupt
}
我在我的按鈕那邊強制觸發HLVD
void Debounce_Tasks(void) {
static bool flagChecked[DEBOUNCE_PIN_MAX];
bool flagDebugMessage = false;
getInputPin();
for (size_t pinIndex = 0; pinIndex < DEBOUNCE_PIN_MAX; pinIndex++) {
if (object[pinIndex].pinSetting.pullState == PULL_STATE_NONE) {
// 設置浮接的輸入腳不偵測
if (flagChecked[pinIndex] == false) {
flagChecked[pinIndex] = true;
flagDebugMessage = true;
}
Nop();
} else {
if (object[pinIndex].pinSetting.input == object[pinIndex].pinTriggerCondition) {
if (object[pinIndex].pinState != PIN_STATE_PRESSED) {
if ((object[pinIndex].timer[DEBOUNCE_TIMER_PRESS] + 1 >= BOUNCE_TIME)) {
object[pinIndex].pinState = PIN_STATE_PRESSED;
if (pinIndex == DEBOUNCE_PIN_SWITCH_2) {
#ifndef __MPLAB_DEBUGGER_SIMULATOR
ramStart[0] = BTL_TRIGGER_PATTERN;
ramStart[1] = BTL_TRIGGER_PATTERN;
ramStart[2] = BTL_TRIGGER_PATTERN;
ramStart[3] = BTL_TRIGGER_PATTERN;
while (UART5_WriteIsBusy())
;
formatString_Timestamp(timestamp);
sprintf(uartMessage.data, //
"rn%sEntering Bootloader...rn", //
timestamp //
);
uartMessage.len = strlen(uartMessage.data);
UART5_Write(uartMessage.data, uartMessage.len);
while (UART5_TransmitComplete() != true)
;
SYS_RESET_SoftwareReset();
#endif
}
if (pinIndex == DEBOUNCE_PIN_SWITCH_3) {
#ifndef __MPLAB_DEBUGGER_SIMULATOR
formatString_Timestamp(timestamp);
sprintf(uartMessage.data, //
"rn%sRNMICONSET = _RNMICON_HLVD_MASK;rn", //
timestamp //
);
uartMessage.len = strlen(uartMessage.data);
UART_PushTxQueue(UART_6, &uartMessage);
SYSKEY = 0x00000000;
SYSKEY = 0xAA996655;
SYSKEY = 0x556699AA;
RNMICONSET = _RNMICON_HLVD_MASK;
SYSKEY = 0x33333333;
formatString_Timestamp(timestamp);
sprintf(uartMessage.data, //
"rn%sRNMICON = 0x%08X;(%s:%d)rn", //
timestamp, //
RNMICON, //
__FILE__, //
__LINE__);
uartMessage.len = strlen(uartMessage.data);
UART_PushTxQueue(UART_6, &uartMessage);
#endif
}
flagDebugMessage = true;
} else {
object[pinIndex].timer[DEBOUNCE_TIMER_PRESS]++;
}
}
object[pinIndex].timer[DEBOUNCE_TIMER_RELEASE] = 0;
} else {
if (object[pinIndex].pinState != PIN_STATE_RELEASED) {
if (object[pinIndex].timer[DEBOUNCE_TIMER_RELEASE] + 1 >= BOUNCE_TIME) {
object[pinIndex].pinState = PIN_STATE_RELEASED;
flagDebugMessage = true;
} else {
object[pinIndex].timer[DEBOUNCE_TIMER_RELEASE]++;
}
}
object[pinIndex].timer[DEBOUNCE_TIMER_PRESS] = 0;
}
}
if (flagDebugMessage) {
flagDebugMessage = false;
formatString_Debounce(object[pinIndex].pinState, pinIndex);
}
}
}
我進Debug看, 我始終沒有進入過NMI, 然後我就在while加入polling RNMICON
if ((RNMICON & _RNMICON_HLVD_MASK) == _RNMICON_HLVD_MASK) {
// Programmable High/Low-Voltage Detect
SYSKEY = 0x00000000;
SYSKEY = 0xAA996655;
SYSKEY = 0x556699AA;
formatString_Timestamp(timestamp);
sprintf(uartMessage.data, //
"rn%sRNMICON = 0x%08X;(%s:%d)rn", //
timestamp, //
RNMICON, //
__FILE__, //
__LINE__);
uartMessage.len = strlen(uartMessage.data);
UART_PushTxQueue(UART_6, &uartMessage);
RNMICONCLR = _RNMICON_HLVD_MASK;
SYSKEY = 0x33333333;
}
這樣我可以強制舉旗RNMICON->HLVD, 但無法舉旗HLVDCON->HLEVT, 我猜是HLVD沒有被開啟, 但也沒有PMD使它開啟
以上是我測試的方法, 但我都沒有辦法觸發HLVD與進入NMI.