Skip to content

Commit 7a074a1

Browse files
committed
cc3200: Implement safe boot pin and system led behaviour.
The safe boot pin, when pulled high during reset rolls back the firmware to the "factory" image and skips execution of 'boot.py' and 'main.py'. This is useful to recover from a crash condition. The system led is used mostly to signal errors.
1 parent 8a5aee1 commit 7a074a1

10 files changed

Lines changed: 172 additions & 75 deletions

File tree

cc3200/boards/LAUNCHXL/mpconfigboard.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,12 @@
3737
#define MICROPY_STDIO_UART PYB_UART_0
3838
#define MICROPY_STDIO_UART_BAUD 115200
3939

40+
#define MICROPY_SYS_LED_PRCM PRCM_GPIOA1
41+
#define MICROPY_SAFE_BOOT_PRCM PRCM_GPIOA2
42+
#define MICROPY_SYS_LED_PORT GPIOA1_BASE
43+
#define MICROPY_SAFE_BOOT_PORT GPIOA2_BASE
44+
#define MICROPY_SYS_LED_PIN_NUM PIN_64 // GPIO9
45+
#define MICROPY_SAFE_BOOT_PIN_NUM PIN_15 // GPIO22
46+
#define MICROPY_SYS_LED_PORT_PIN GPIO_PIN_1
47+
#define MICROPY_SAFE_BOOT_PORT_PIN GPIO_PIN_6
48+

cc3200/bootmgr/bootloader.mk

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ BOOT_INC += -Ibootmgr/sl
55
BOOT_INC += -Ihal
66
BOOT_INC += -Ihal/inc
77
BOOT_INC += -I../drivers/cc3100/inc
8+
BOOT_INC += -Imisc
89
BOOT_INC += -Imods
910
BOOT_INC += -Isimplelink
1011
BOOT_INC += -Isimplelink/oslib
@@ -39,6 +40,10 @@ BOOT_CC3100_SRC_C = $(addprefix drivers/cc3100/,\
3940
src/wlan.c \
4041
)
4142

43+
BOOT_MISC_SRC_C = $(addprefix misc/,\
44+
mperror.c \
45+
)
46+
4247
BOOT_MODS_SRC_C = $(addprefix mods/,\
4348
pybwdt.c \
4449
)
@@ -68,7 +73,7 @@ BOOT_STM_SRC_C = $(addprefix stmhal/,\
6873
)
6974

7075
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))
71-
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))
76+
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))
7277

7378
# Add the linker script
7479
LINKER_SCRIPT = bootmgr/bootmgr.lds
@@ -90,6 +95,7 @@ ifeq ($(BTYPE), debug)
9095
CFLAGS += -DDEBUG=DEBUG
9196
# Optimize the stable sources only
9297
$(BUILD)/hal/%.o: CFLAGS += -Os
98+
$(BUILD)/misc/%.o: CFLAGS += -Os
9399
$(BUILD)/simplelink/%.o: CFLAGS += -Os
94100
$(BUILD)/drivers/cc3100/%.o: CFLAGS += -Os
95101
$(BUILD)/py/%.o: CFLAGS += -Os

cc3200/bootmgr/main.c

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@
2626

2727
#include <stdint.h>
2828
#include <stdbool.h>
29-
3029
#include <std.h>
30+
31+
#include "py/mpconfig.h"
32+
#include MICROPY_HAL_H
3133
#include "hw_ints.h"
3234
#include "hw_types.h"
3335
#include "hw_gpio.h"
@@ -50,6 +52,7 @@
5052
#include "cc3200_hal.h"
5153
#include "debug.h"
5254
#include "pybwdt.h"
55+
#include "mperror.h"
5356

5457

5558
//*****************************************************************************
@@ -60,19 +63,11 @@
6063
#define BOOTMGR_HASH_SIZE 32
6164
#define BOOTMGR_BUFF_SIZE 512
6265

63-
#define BOOTMGR_WAIT_SAFE_MODE_MS 2000
64-
#define BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS 250
65-
66-
#define BOOTMGR_SAFE_MODE_ENTER_MS 1000
67-
#define BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS 100
68-
69-
#define BOOTMGR_PINS_PRCM PRCM_GPIOA3
70-
#define BOOTMGR_PINS_PORT GPIOA3_BASE
71-
#define BOOTMGR_LED_PIN_NUM PIN_21
72-
#define BOOTMGR_SFE_PIN_NUM PIN_18
73-
#define BOOTMGR_LED_PORT_PIN GPIO_PIN_1 // GPIO25
74-
#define BOOTMGR_SFE_PORT_PIN GPIO_PIN_4 // GPIO28
66+
#define BOOTMGR_WAIT_SAFE_MODE_MS 1600
67+
#define BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS 200
7568

69+
#define BOOTMGR_SAFE_MODE_ENTER_MS 700
70+
#define BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS 70
7671

7772
//*****************************************************************************
7873
// Exported functions declarations
@@ -159,18 +154,12 @@ static void bootmgr_board_init(void) {
159154
// Enable the Data Hashing Engine
160155
HASH_Init();
161156

162-
// Enable GPIOA3 Peripheral Clock
163-
MAP_PRCMPeripheralClkEnable(BOOTMGR_PINS_PRCM, PRCM_RUN_MODE_CLK);
164-
165-
// Configure the bld
166-
MAP_PinTypeGPIO(BOOTMGR_LED_PIN_NUM, PIN_MODE_0, false);
167-
MAP_PinConfigSet(BOOTMGR_LED_PIN_NUM, PIN_STRENGTH_6MA, PIN_TYPE_STD);
168-
MAP_GPIODirModeSet(BOOTMGR_PINS_PORT, BOOTMGR_LED_PORT_PIN, GPIO_DIR_MODE_OUT);
157+
// Init the system led and the system switch
158+
mperror_init0();
169159

170-
// Configure the safe mode pin
171-
MAP_PinTypeGPIO(BOOTMGR_SFE_PIN_NUM, PIN_MODE_0, false);
172-
MAP_PinConfigSet(BOOTMGR_SFE_PIN_NUM, PIN_STRENGTH_4MA, PIN_TYPE_STD_PU);
173-
MAP_GPIODirModeSet(BOOTMGR_PINS_PORT, BOOTMGR_SFE_PORT_PIN, GPIO_DIR_MODE_IN);
160+
// clear the safe boot request, since we should not trust
161+
// the register's state after reset
162+
mperror_clear_safe_boot();
174163
}
175164

176165
//*****************************************************************************
@@ -252,13 +241,14 @@ static void bootmgr_load_and_execute (_u8 *image) {
252241
//*****************************************************************************
253242
static bool safe_mode_boot (void) {
254243
_u32 count = 0;
255-
while (!MAP_GPIOPinRead(BOOTMGR_PINS_PORT, BOOTMGR_SFE_PORT_PIN) &&
256-
((BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS * count++) < BOOTMGR_WAIT_SAFE_MODE_MS)) {
244+
while (MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) &&
245+
((BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS * count++) < BOOTMGR_WAIT_SAFE_MODE_MS)) {
257246
// toogle the led
258-
MAP_GPIOPinWrite(BOOTMGR_PINS_PORT, BOOTMGR_LED_PORT_PIN, ~MAP_GPIOPinRead(GPIOA3_BASE, BOOTMGR_LED_PORT_PIN));
247+
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN));
259248
UtilsDelay(UTILS_DELAY_US_TO_COUNT(BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS * 1000));
260249
}
261-
return MAP_GPIOPinRead(BOOTMGR_PINS_PORT, BOOTMGR_SFE_PORT_PIN) ? false : true;
250+
mperror_deinit_sfe_pin();
251+
return MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) ? true : false;
262252
}
263253

264254
//*****************************************************************************
@@ -268,14 +258,16 @@ static void bootmgr_image_loader(sBootInfo_t *psBootInfo) {
268258
_i32 fhandle;
269259
if (safe_mode_boot()) {
270260
_u32 count = 0;
271-
while ((BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS * count++) > BOOTMGR_SAFE_MODE_ENTER_MS) {
261+
while ((BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS * count++) < BOOTMGR_SAFE_MODE_ENTER_MS) {
272262
// toogle the led
273-
MAP_GPIOPinWrite(BOOTMGR_PINS_PORT, BOOTMGR_LED_PORT_PIN, ~MAP_GPIOPinRead(GPIOA3_BASE, BOOTMGR_LED_PORT_PIN));
263+
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN));
274264
UtilsDelay(UTILS_DELAY_US_TO_COUNT(BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS * 1000));
275265
}
276266
psBootInfo->ActiveImg = IMG_ACT_FACTORY;
277267
// turn the led off
278-
MAP_GPIOPinWrite(BOOTMGR_PINS_PORT, BOOTMGR_LED_PORT_PIN, 0);
268+
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, 0);
269+
// request a safe boot to the application
270+
mperror_request_safe_boot();
279271
}
280272
// do we have a new update image that needs to be verified?
281273
else if ((psBootInfo->ActiveImg == IMG_ACT_UPDATE) && (psBootInfo->Status == IMG_STATUS_CHECK)) {
@@ -350,7 +342,7 @@ int main (void) {
350342
// could not be loaded, so, loop forever and signal the crash to the user
351343
while (true) {
352344
// keep the bld on
353-
MAP_GPIOPinWrite(BOOTMGR_PINS_PORT, BOOTMGR_LED_PORT_PIN, BOOTMGR_LED_PORT_PIN);
345+
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, MICROPY_SYS_LED_PORT_PIN);
354346
__asm volatile(" dsb \n"
355347
" isb \n"
356348
" wfi \n");

cc3200/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ int main (void) {
6363
// Initialize the clocks and the interrupt system
6464
HAL_SystemInit();
6565

66-
// Start the watchdog
66+
// Init the watchdog
6767
pybwdt_init0();
6868

6969
#ifdef DEBUG

cc3200/misc/FreeRTOSHooks.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "pybuart.h"
3636
#include "osi.h"
3737
#include "pybwdt.h"
38+
#include "mperror.h"
3839

3940

4041
//*****************************************************************************
@@ -66,15 +67,13 @@ void vApplicationIdleHook (void)
6667
void vApplicationMallocFailedHook (void)
6768
{
6869
#ifdef DEBUG
69-
// Break into the debugger
70+
// break into the debugger
7071
__asm volatile ("bkpt #0 \n");
71-
72-
printf("\nFATAL ERROR: FreeRTOS malloc failed!\n");
7372
#endif
7473

7574
for ( ; ; )
7675
{
77-
// TODO: Blink the BLD
76+
__fatal_error("FreeRTOS malloc failed!");
7877
}
7978
}
8079

@@ -92,13 +91,11 @@ void vApplicationStackOverflowHook (OsiTaskHandle *pxTask, signed char *pcTaskNa
9291
#ifdef DEBUG
9392
// Break into the debugger
9493
__asm volatile ("bkpt #0 \n");
95-
96-
printf("\nFATAL ERROR: Application: %s stack overflow!\n", pcTaskName);
9794
#endif
9895

9996
for ( ; ; )
10097
{
101-
// TODO: Blink the BLD
98+
__fatal_error("Stack overflow!");
10299
}
103100
}
104101

cc3200/misc/mperror.c

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,88 @@
3232
#include "py/mpconfig.h"
3333
#include MICROPY_HAL_H
3434
#include "py/obj.h"
35-
#include "inc/hw_memmap.h"
35+
#include "hw_ints.h"
36+
#include "hw_types.h"
37+
#include "hw_gpio.h"
38+
#include "hw_memmap.h"
39+
#include "hw_gprcm.h"
40+
#include "hw_common_reg.h"
41+
#include "pin.h"
42+
#include "gpio.h"
43+
#include "rom.h"
44+
#include "rom_map.h"
45+
#include "prcm.h"
3646
#include "pybuart.h"
3747
#include "utils.h"
3848

3949

50+
#define MPERROR_TOOGLE_MS (200)
51+
#define MPERROR_SIGNAL_ERROR_MS (2000)
52+
53+
#define MPERROR_SAFE_BOOT_REG_IDX (0)
54+
55+
56+
void mperror_init0 (void) {
57+
// Enable SYS GPIOs peripheral clocks
58+
MAP_PRCMPeripheralClkEnable(MICROPY_SYS_LED_PRCM, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
59+
#ifdef BOOTLOADER
60+
MAP_PRCMPeripheralClkEnable(MICROPY_SAFE_BOOT_PRCM, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
61+
#endif
62+
63+
// Configure the bld
64+
MAP_PinTypeGPIO(MICROPY_SYS_LED_PIN_NUM, PIN_MODE_0, false);
65+
MAP_PinConfigSet(MICROPY_SYS_LED_PIN_NUM, PIN_STRENGTH_6MA, PIN_TYPE_STD);
66+
MAP_GPIODirModeSet(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, GPIO_DIR_MODE_OUT);
67+
68+
#ifdef BOOTLOADER
69+
// Configure the safe boot pin
70+
MAP_PinTypeGPIO(MICROPY_SAFE_BOOT_PIN_NUM, PIN_MODE_0, false);
71+
MAP_PinConfigSet(MICROPY_SAFE_BOOT_PIN_NUM, PIN_STRENGTH_4MA, PIN_TYPE_STD_PD);
72+
MAP_GPIODirModeSet(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN, GPIO_DIR_MODE_IN);
73+
#endif
74+
}
75+
76+
void mperror_deinit_sfe_pin (void) {
77+
// disable the pull-down
78+
MAP_PinConfigSet(MICROPY_SAFE_BOOT_PIN_NUM, PIN_STRENGTH_4MA, PIN_TYPE_STD);
79+
}
80+
81+
void mperror_signal_error (void) {
82+
uint32_t count = 0;
83+
while ((MPERROR_TOOGLE_MS * count++) > MPERROR_SIGNAL_ERROR_MS) {
84+
// toogle the led
85+
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN));
86+
UtilsDelay(UTILS_DELAY_US_TO_COUNT(MPERROR_TOOGLE_MS * 1000));
87+
}
88+
}
89+
90+
void mperror_request_safe_boot (void) {
91+
MAP_PRCMOCRRegisterWrite(MPERROR_SAFE_BOOT_REG_IDX, 1);
92+
}
93+
94+
void mperror_clear_safe_boot (void) {
95+
MAP_PRCMOCRRegisterWrite(MPERROR_SAFE_BOOT_REG_IDX, 0);
96+
}
97+
98+
// returns the last state of the safe boot request and clears the register
99+
bool mperror_safe_boot_requested (void) {
100+
bool ret = MAP_PRCMOCRRegisterRead(MPERROR_SAFE_BOOT_REG_IDX);
101+
mperror_clear_safe_boot();
102+
return ret;
103+
}
104+
40105
void NORETURN __fatal_error(const char *msg) {
106+
#ifdef DEBUG
41107
if (msg != NULL) {
42108
// wait for 20ms
43109
UtilsDelay(UTILS_DELAY_US_TO_COUNT(20000));
44110
mp_hal_stdout_tx_str("\r\nFATAL ERROR:");
45111
mp_hal_stdout_tx_str(msg);
46112
mp_hal_stdout_tx_str("\r\n");
47113
}
114+
#endif
115+
// signal the crash with the system led
116+
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, MICROPY_SYS_LED_PORT_PIN);
48117
for ( ;; ) {__WFI();}
49118
}
50119

@@ -63,4 +132,3 @@ void nlr_jump_fail(void *val) {
63132
__fatal_error(NULL);
64133
#endif
65134
}
66-

cc3200/misc/mperror.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,16 @@
2525
* THE SOFTWARE.
2626
*/
2727

28-
#ifdef DEBUG
28+
#ifndef MPERROR_H_
29+
#define MPERROR_H_
30+
2931
extern void NORETURN __fatal_error(const char *msg);
30-
#else
31-
#define __fatal_error(...) for ( ;; ) {__WFI();}
32-
#endif
32+
33+
void mperror_init0 (void);
34+
void mperror_deinit_sfe_pin (void);
35+
void mperror_signal_error (void);
36+
void mperror_request_safe_boot (void);
37+
void mperror_clear_safe_boot (void);
38+
bool mperror_safe_boot_requested (void);
39+
40+
#endif // MPERROR_H_

cc3200/mods/pybextint.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "mpexception.h"
4747
#include "interrupt.h"
4848
#include "cc3200_asm.h"
49+
#include "mperror.h"
4950

5051
/// \moduleref pyb
5152
/// \class ExtInt - configure I/O pins to interrupt on external events
@@ -218,8 +219,8 @@ STATIC void ExecuteIntCallback (extint_obj_t *self) {
218219
extint_disable(self);
219220
// printing an exception here will cause a stack overflow that ends up in a
220221
// hard fault so, is better to signal the uncaught (probably non-recoverable)
221-
// exception by blinkg the BLD
222-
// TODO: Blink the BLD
222+
// exception by blinkg the system led
223+
mperror_signal_error();
223224
}
224225
gc_unlock();
225226
enable_irq(primsk);

0 commit comments

Comments
 (0)