diff --git a/cc3200/boards/LAUNCHXL/mpconfigboard.h b/cc3200/boards/LAUNCHXL/mpconfigboard.h index c4472c77bd..2d12d4f6cb 100644 --- a/cc3200/boards/LAUNCHXL/mpconfigboard.h +++ b/cc3200/boards/LAUNCHXL/mpconfigboard.h @@ -37,3 +37,12 @@ #define MICROPY_STDIO_UART PYB_UART_0 #define MICROPY_STDIO_UART_BAUD 115200 +#define MICROPY_SYS_LED_PRCM PRCM_GPIOA1 +#define MICROPY_SAFE_BOOT_PRCM PRCM_GPIOA2 +#define MICROPY_SYS_LED_PORT GPIOA1_BASE +#define MICROPY_SAFE_BOOT_PORT GPIOA2_BASE +#define MICROPY_SYS_LED_PIN_NUM PIN_64 // GPIO9 +#define MICROPY_SAFE_BOOT_PIN_NUM PIN_15 // GPIO22 +#define MICROPY_SYS_LED_PORT_PIN GPIO_PIN_1 +#define MICROPY_SAFE_BOOT_PORT_PIN GPIO_PIN_6 + diff --git a/cc3200/bootmgr/bootloader.mk b/cc3200/bootmgr/bootloader.mk index 64d7f671a9..1f687d9b88 100644 --- a/cc3200/bootmgr/bootloader.mk +++ b/cc3200/bootmgr/bootloader.mk @@ -5,6 +5,7 @@ BOOT_INC += -Ibootmgr/sl BOOT_INC += -Ihal BOOT_INC += -Ihal/inc BOOT_INC += -I../drivers/cc3100/inc +BOOT_INC += -Imisc BOOT_INC += -Imods BOOT_INC += -Isimplelink BOOT_INC += -Isimplelink/oslib @@ -39,6 +40,10 @@ BOOT_CC3100_SRC_C = $(addprefix drivers/cc3100/,\ src/wlan.c \ ) +BOOT_MISC_SRC_C = $(addprefix misc/,\ + mperror.c \ + ) + BOOT_MODS_SRC_C = $(addprefix mods/,\ pybwdt.c \ ) @@ -68,7 +73,7 @@ BOOT_STM_SRC_C = $(addprefix stmhal/,\ ) OBJ = $(addprefix $(BUILD)/, $(BOOT_HAL_SRC_C:.c=.o) $(BOOT_MODS_SRC_C:.c=.o) $(BOOT_SL_SRC_C:.c=.o) $(BOOT_CC3100_SRC_C:.c=.o) $(BOOT_UTIL_SRC_C:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(BOOT_MAIN_SRC_C:.c=.o) $(BOOT_MAIN_SRC_S:.s=.o) $(BOOT_PY_SRC_C:.c=.o) $(BOOT_STM_SRC_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(BOOT_MISC_SRC_C:.c=.o) $(BOOT_MAIN_SRC_C:.c=.o) $(BOOT_MAIN_SRC_S:.s=.o) $(BOOT_PY_SRC_C:.c=.o) $(BOOT_STM_SRC_C:.c=.o)) # Add the linker script LINKER_SCRIPT = bootmgr/bootmgr.lds @@ -90,6 +95,7 @@ ifeq ($(BTYPE), debug) CFLAGS += -DDEBUG=DEBUG # Optimize the stable sources only $(BUILD)/hal/%.o: CFLAGS += -Os +$(BUILD)/misc/%.o: CFLAGS += -Os $(BUILD)/simplelink/%.o: CFLAGS += -Os $(BUILD)/drivers/cc3100/%.o: CFLAGS += -Os $(BUILD)/py/%.o: CFLAGS += -Os diff --git a/cc3200/bootmgr/main.c b/cc3200/bootmgr/main.c index 839e23ecdd..0e7ecd01b0 100644 --- a/cc3200/bootmgr/main.c +++ b/cc3200/bootmgr/main.c @@ -26,8 +26,10 @@ #include #include - #include + +#include "py/mpconfig.h" +#include MICROPY_HAL_H #include "hw_ints.h" #include "hw_types.h" #include "hw_gpio.h" @@ -50,6 +52,7 @@ #include "cc3200_hal.h" #include "debug.h" #include "pybwdt.h" +#include "mperror.h" //***************************************************************************** @@ -60,19 +63,11 @@ #define BOOTMGR_HASH_SIZE 32 #define BOOTMGR_BUFF_SIZE 512 -#define BOOTMGR_WAIT_SAFE_MODE_MS 2000 -#define BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS 250 - -#define BOOTMGR_SAFE_MODE_ENTER_MS 1000 -#define BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS 100 - -#define BOOTMGR_PINS_PRCM PRCM_GPIOA3 -#define BOOTMGR_PINS_PORT GPIOA3_BASE -#define BOOTMGR_LED_PIN_NUM PIN_21 -#define BOOTMGR_SFE_PIN_NUM PIN_18 -#define BOOTMGR_LED_PORT_PIN GPIO_PIN_1 // GPIO25 -#define BOOTMGR_SFE_PORT_PIN GPIO_PIN_4 // GPIO28 +#define BOOTMGR_WAIT_SAFE_MODE_MS 1600 +#define BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS 200 +#define BOOTMGR_SAFE_MODE_ENTER_MS 700 +#define BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS 70 //***************************************************************************** // Exported functions declarations @@ -159,18 +154,12 @@ static void bootmgr_board_init(void) { // Enable the Data Hashing Engine HASH_Init(); - // Enable GPIOA3 Peripheral Clock - MAP_PRCMPeripheralClkEnable(BOOTMGR_PINS_PRCM, PRCM_RUN_MODE_CLK); + // Init the system led and the system switch + mperror_init0(); - // Configure the bld - MAP_PinTypeGPIO(BOOTMGR_LED_PIN_NUM, PIN_MODE_0, false); - MAP_PinConfigSet(BOOTMGR_LED_PIN_NUM, PIN_STRENGTH_6MA, PIN_TYPE_STD); - MAP_GPIODirModeSet(BOOTMGR_PINS_PORT, BOOTMGR_LED_PORT_PIN, GPIO_DIR_MODE_OUT); - - // Configure the safe mode pin - MAP_PinTypeGPIO(BOOTMGR_SFE_PIN_NUM, PIN_MODE_0, false); - MAP_PinConfigSet(BOOTMGR_SFE_PIN_NUM, PIN_STRENGTH_4MA, PIN_TYPE_STD_PU); - MAP_GPIODirModeSet(BOOTMGR_PINS_PORT, BOOTMGR_SFE_PORT_PIN, GPIO_DIR_MODE_IN); + // clear the safe boot request, since we should not trust + // the register's state after reset + mperror_clear_safe_boot(); } //***************************************************************************** @@ -252,13 +241,14 @@ static void bootmgr_load_and_execute (_u8 *image) { //***************************************************************************** static bool safe_mode_boot (void) { _u32 count = 0; - while (!MAP_GPIOPinRead(BOOTMGR_PINS_PORT, BOOTMGR_SFE_PORT_PIN) && - ((BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS * count++) < BOOTMGR_WAIT_SAFE_MODE_MS)) { + while (MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) && + ((BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS * count++) < BOOTMGR_WAIT_SAFE_MODE_MS)) { // toogle the led - MAP_GPIOPinWrite(BOOTMGR_PINS_PORT, BOOTMGR_LED_PORT_PIN, ~MAP_GPIOPinRead(GPIOA3_BASE, BOOTMGR_LED_PORT_PIN)); + MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN)); UtilsDelay(UTILS_DELAY_US_TO_COUNT(BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS * 1000)); } - return MAP_GPIOPinRead(BOOTMGR_PINS_PORT, BOOTMGR_SFE_PORT_PIN) ? false : true; + mperror_deinit_sfe_pin(); + return MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) ? true : false; } //***************************************************************************** @@ -268,14 +258,16 @@ static void bootmgr_image_loader(sBootInfo_t *psBootInfo) { _i32 fhandle; if (safe_mode_boot()) { _u32 count = 0; - while ((BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS * count++) > BOOTMGR_SAFE_MODE_ENTER_MS) { + while ((BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS * count++) < BOOTMGR_SAFE_MODE_ENTER_MS) { // toogle the led - MAP_GPIOPinWrite(BOOTMGR_PINS_PORT, BOOTMGR_LED_PORT_PIN, ~MAP_GPIOPinRead(GPIOA3_BASE, BOOTMGR_LED_PORT_PIN)); + MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN)); UtilsDelay(UTILS_DELAY_US_TO_COUNT(BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS * 1000)); } psBootInfo->ActiveImg = IMG_ACT_FACTORY; // turn the led off - MAP_GPIOPinWrite(BOOTMGR_PINS_PORT, BOOTMGR_LED_PORT_PIN, 0); + MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, 0); + // request a safe boot to the application + mperror_request_safe_boot(); } // do we have a new update image that needs to be verified? else if ((psBootInfo->ActiveImg == IMG_ACT_UPDATE) && (psBootInfo->Status == IMG_STATUS_CHECK)) { @@ -350,7 +342,7 @@ int main (void) { // could not be loaded, so, loop forever and signal the crash to the user while (true) { // keep the bld on - MAP_GPIOPinWrite(BOOTMGR_PINS_PORT, BOOTMGR_LED_PORT_PIN, BOOTMGR_LED_PORT_PIN); + MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, MICROPY_SYS_LED_PORT_PIN); __asm volatile(" dsb \n" " isb \n" " wfi \n"); diff --git a/cc3200/main.c b/cc3200/main.c index 6f0ce3f1b6..24a42c5247 100644 --- a/cc3200/main.c +++ b/cc3200/main.c @@ -63,7 +63,7 @@ int main (void) { // Initialize the clocks and the interrupt system HAL_SystemInit(); - // Start the watchdog + // Init the watchdog pybwdt_init0(); #ifdef DEBUG diff --git a/cc3200/misc/FreeRTOSHooks.c b/cc3200/misc/FreeRTOSHooks.c index 4268980d6c..9383000b0e 100644 --- a/cc3200/misc/FreeRTOSHooks.c +++ b/cc3200/misc/FreeRTOSHooks.c @@ -35,6 +35,7 @@ #include "pybuart.h" #include "osi.h" #include "pybwdt.h" +#include "mperror.h" //***************************************************************************** @@ -66,15 +67,13 @@ void vApplicationIdleHook (void) void vApplicationMallocFailedHook (void) { #ifdef DEBUG - // Break into the debugger + // break into the debugger __asm volatile ("bkpt #0 \n"); - - printf("\nFATAL ERROR: FreeRTOS malloc failed!\n"); #endif for ( ; ; ) { - // TODO: Blink the BLD + __fatal_error("FreeRTOS malloc failed!"); } } @@ -92,13 +91,11 @@ void vApplicationStackOverflowHook (OsiTaskHandle *pxTask, signed char *pcTaskNa #ifdef DEBUG // Break into the debugger __asm volatile ("bkpt #0 \n"); - - printf("\nFATAL ERROR: Application: %s stack overflow!\n", pcTaskName); #endif for ( ; ; ) { - // TODO: Blink the BLD + __fatal_error("Stack overflow!"); } } diff --git a/cc3200/misc/mperror.c b/cc3200/misc/mperror.c index a615a0f06d..bfb17a2b41 100644 --- a/cc3200/misc/mperror.c +++ b/cc3200/misc/mperror.c @@ -32,12 +32,78 @@ #include "py/mpconfig.h" #include MICROPY_HAL_H #include "py/obj.h" -#include "inc/hw_memmap.h" +#include "hw_ints.h" +#include "hw_types.h" +#include "hw_gpio.h" +#include "hw_memmap.h" +#include "hw_gprcm.h" +#include "hw_common_reg.h" +#include "pin.h" +#include "gpio.h" +#include "rom.h" +#include "rom_map.h" +#include "prcm.h" #include "pybuart.h" #include "utils.h" +#define MPERROR_TOOGLE_MS (200) +#define MPERROR_SIGNAL_ERROR_MS (2000) + +#define MPERROR_SAFE_BOOT_REG_IDX (0) + + +void mperror_init0 (void) { + // Enable SYS GPIOs peripheral clocks + MAP_PRCMPeripheralClkEnable(MICROPY_SYS_LED_PRCM, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); +#ifdef BOOTLOADER + MAP_PRCMPeripheralClkEnable(MICROPY_SAFE_BOOT_PRCM, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); +#endif + + // Configure the bld + MAP_PinTypeGPIO(MICROPY_SYS_LED_PIN_NUM, PIN_MODE_0, false); + MAP_PinConfigSet(MICROPY_SYS_LED_PIN_NUM, PIN_STRENGTH_6MA, PIN_TYPE_STD); + MAP_GPIODirModeSet(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, GPIO_DIR_MODE_OUT); + +#ifdef BOOTLOADER + // Configure the safe boot pin + MAP_PinTypeGPIO(MICROPY_SAFE_BOOT_PIN_NUM, PIN_MODE_0, false); + MAP_PinConfigSet(MICROPY_SAFE_BOOT_PIN_NUM, PIN_STRENGTH_4MA, PIN_TYPE_STD_PD); + MAP_GPIODirModeSet(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN, GPIO_DIR_MODE_IN); +#endif +} + +void mperror_deinit_sfe_pin (void) { + // disable the pull-down + MAP_PinConfigSet(MICROPY_SAFE_BOOT_PIN_NUM, PIN_STRENGTH_4MA, PIN_TYPE_STD); +} + +void mperror_signal_error (void) { + uint32_t count = 0; + while ((MPERROR_TOOGLE_MS * count++) > MPERROR_SIGNAL_ERROR_MS) { + // toogle the led + MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN)); + UtilsDelay(UTILS_DELAY_US_TO_COUNT(MPERROR_TOOGLE_MS * 1000)); + } +} + +void mperror_request_safe_boot (void) { + MAP_PRCMOCRRegisterWrite(MPERROR_SAFE_BOOT_REG_IDX, 1); +} + +void mperror_clear_safe_boot (void) { + MAP_PRCMOCRRegisterWrite(MPERROR_SAFE_BOOT_REG_IDX, 0); +} + +// returns the last state of the safe boot request and clears the register +bool mperror_safe_boot_requested (void) { + bool ret = MAP_PRCMOCRRegisterRead(MPERROR_SAFE_BOOT_REG_IDX); + mperror_clear_safe_boot(); + return ret; +} + void NORETURN __fatal_error(const char *msg) { +#ifdef DEBUG if (msg != NULL) { // wait for 20ms UtilsDelay(UTILS_DELAY_US_TO_COUNT(20000)); @@ -45,6 +111,9 @@ void NORETURN __fatal_error(const char *msg) { mp_hal_stdout_tx_str(msg); mp_hal_stdout_tx_str("\r\n"); } +#endif + // signal the crash with the system led + MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, MICROPY_SYS_LED_PORT_PIN); for ( ;; ) {__WFI();} } @@ -63,4 +132,3 @@ void nlr_jump_fail(void *val) { __fatal_error(NULL); #endif } - diff --git a/cc3200/misc/mperror.h b/cc3200/misc/mperror.h index 89a2abe8ef..827d00a9f0 100644 --- a/cc3200/misc/mperror.h +++ b/cc3200/misc/mperror.h @@ -25,8 +25,16 @@ * THE SOFTWARE. */ -#ifdef DEBUG +#ifndef MPERROR_H_ +#define MPERROR_H_ + extern void NORETURN __fatal_error(const char *msg); -#else -#define __fatal_error(...) for ( ;; ) {__WFI();} -#endif + +void mperror_init0 (void); +void mperror_deinit_sfe_pin (void); +void mperror_signal_error (void); +void mperror_request_safe_boot (void); +void mperror_clear_safe_boot (void); +bool mperror_safe_boot_requested (void); + +#endif // MPERROR_H_ diff --git a/cc3200/mods/pybextint.c b/cc3200/mods/pybextint.c index a98dbdba78..c135c4f560 100644 --- a/cc3200/mods/pybextint.c +++ b/cc3200/mods/pybextint.c @@ -46,6 +46,7 @@ #include "mpexception.h" #include "interrupt.h" #include "cc3200_asm.h" +#include "mperror.h" /// \moduleref pyb /// \class ExtInt - configure I/O pins to interrupt on external events @@ -218,8 +219,8 @@ STATIC void ExecuteIntCallback (extint_obj_t *self) { extint_disable(self); // printing an exception here will cause a stack overflow that ends up in a // hard fault so, is better to signal the uncaught (probably non-recoverable) - // exception by blinkg the BLD - // TODO: Blink the BLD + // exception by blinkg the system led + mperror_signal_error(); } gc_unlock(); enable_irq(primsk); diff --git a/cc3200/mptask.c b/cc3200/mptask.c index 90bb7e9a29..733191969c 100644 --- a/cc3200/mptask.c +++ b/cc3200/mptask.c @@ -96,12 +96,20 @@ void TASK_Micropython (void *pvParameters) { // Initialize the garbage collector with the top of our stack uint32_t sp = gc_helper_get_sp(); gc_collect_init (sp); + bool safeboot; FRESULT res; #if MICROPY_HW_ENABLE_RTC pybrtc_init(); #endif +#ifdef DEBUG + mperror_init0(); + safeboot = false; +#else + safeboot = mperror_safe_boot_requested(); +#endif + // Create the simple link spawn task ASSERT (OSI_OK == VStartSimpleLinkSpawnTask(SIMPLELINK_SPAWN_TASK_PRIORITY)); @@ -170,16 +178,19 @@ soft_reset: // reset config variables; they should be set by boot.py MP_STATE_PORT(pyb_config_main) = MP_OBJ_NULL; - // run boot.py, if it exists - const char *boot_py = "BOOT.PY"; - res = f_stat(boot_py, NULL); - if (res == FR_OK) { - int ret = pyexec_file(boot_py); - if (ret & PYEXEC_FORCED_EXIT) { - goto soft_reset_exit; - } - if (!ret) { - // TODO: Flash some LEDs + if (!safeboot) { + // run boot.py, if it exists + const char *boot_py = "BOOT.PY"; + res = f_stat(boot_py, NULL); + if (res == FR_OK) { + int ret = pyexec_file(boot_py); + if (ret & PYEXEC_FORCED_EXIT) { + goto soft_reset_exit; + } + if (!ret) { + // flash the system led + mperror_signal_error(); + } } } @@ -189,22 +200,25 @@ soft_reset: // At this point everything is fully configured and initialised. - // Run the main script from the current directory. - if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { - const char *main_py; - if (MP_STATE_PORT(pyb_config_main) == MP_OBJ_NULL) { - main_py = "MAIN.PY"; - } else { - main_py = mp_obj_str_get_str(MP_STATE_PORT(pyb_config_main)); - } - res = f_stat(main_py, NULL); - if (res == FR_OK) { - int ret = pyexec_file(main_py); - if (ret & PYEXEC_FORCED_EXIT) { - goto soft_reset_exit; + if (!safeboot) { + // Run the main script from the current directory. + if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { + const char *main_py; + if (MP_STATE_PORT(pyb_config_main) == MP_OBJ_NULL) { + main_py = "MAIN.PY"; + } else { + main_py = mp_obj_str_get_str(MP_STATE_PORT(pyb_config_main)); } - if (!ret) { - // TODO: Flash some LEDs + res = f_stat(main_py, NULL); + if (res == FR_OK) { + int ret = pyexec_file(main_py); + if (ret & PYEXEC_FORCED_EXIT) { + goto soft_reset_exit; + } + if (!ret) { + // flash the system led + mperror_signal_error(); + } } } } diff --git a/cc3200/telnet/telnet.c b/cc3200/telnet/telnet.c index 7d11df913b..31037aed2b 100644 --- a/cc3200/telnet/telnet.c +++ b/cc3200/telnet/telnet.c @@ -36,6 +36,7 @@ #include "debug.h" #include "mpexception.h" #include "serverstask.h" +#include "mperror.h" #include "genhdr/py-version.h" @@ -461,7 +462,8 @@ static bool telnet_send_with_retries (int16_t sd, const void *pBuf, int16_t len) } while (++retries <= TELNET_TX_RETRIES_MAX); } else { - // TODO: blink the BLD + // blink the system led + mperror_signal_error(); } return false;