From e08be6b237e92df1016c18e837619fd5f4379a09 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sat, 9 Jun 2018 21:48:53 +0800 Subject: [PATCH 1/5] Add macros like PINOP to set pin configuration and read pin state --- inc/uf2.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/inc/uf2.h b/inc/uf2.h index ed668047..06b98d17 100644 --- a/inc/uf2.h +++ b/inc/uf2.h @@ -243,6 +243,8 @@ void system_init(void); #define LED_TICK led_tick #define PINOP(pin, OP) (PORT->Group[(pin) / 32].OP.reg = (1 << ((pin) % 32))) +#define PINIP(pin) (((PORT->Group[(pin) / 32].IN.reg) >> ((pin) % 32)) & 0x1) +#define PINCFG(pin, cfg) (PORT->Group[(pin) / 32].PINCFG[(pin) % 32].reg = cfg) void led_tick(void); void led_signal(void); From f2816425c8210986b64b4bc4e1a9fbcce6d5c5f8 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sat, 9 Jun 2018 21:49:39 +0800 Subject: [PATCH 2/5] Add a way to allow a GPIO to hold the bootloader from running the app. --- src/main.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/main.c b/src/main.c index cdcfcbd6..880f1236 100644 --- a/src/main.c +++ b/src/main.c @@ -95,6 +95,26 @@ extern int8_t led_tick_step; static void check_start_application(void) { uint32_t app_start_address; +// Check if there is an IO which will hold us inside the bootloader. +#if defined(HOLD_PIN) && defined(HOLD_STATE) + PINOP(HOLD_PIN, DIRCLR); // Pin is an input + + #if defined(HOLD_PIN_PULLUP) + PINCFG(HOLD_PIN, 0x06); + PINOP(HOLD_PIN, OUTSET); // Pin is pulled up. + #elif defined(HOLD_PIN_PULLDOWN) + PINCFG(HOLD_PIN, 0x06); + PINOP(HOLD_PIN, OUTCLR); // Pin is pulled up. + #else + PINCFG(HOLD_PIN, 0x02); + #endif + + if (PINIP(HOLD_PIN) == HOLD_STATE) { + /* Stay in bootloader */ + return; + } +#endif + /* Load the Reset Handler address of the application */ app_start_address = *(uint32_t *)(APP_START_ADDRESS + 4); From e06e6c7b795609eed4a17e70ba163f9340aa62a1 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Mon, 11 Jun 2018 12:35:56 +0800 Subject: [PATCH 3/5] Change pinconfig to not use magic numbers. Same code size, more readable. --- src/main.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main.c b/src/main.c index 880f1236..4d0953b4 100644 --- a/src/main.c +++ b/src/main.c @@ -97,17 +97,21 @@ static void check_start_application(void) { // Check if there is an IO which will hold us inside the bootloader. #if defined(HOLD_PIN) && defined(HOLD_STATE) + PORT_PINCFG_Type pincfg = {0}; + pincfg.bit.PMUXEN = false; + pincfg.bit.INEN = true; + pincfg.bit.DRVSTR = true; + PINOP(HOLD_PIN, DIRCLR); // Pin is an input #if defined(HOLD_PIN_PULLUP) - PINCFG(HOLD_PIN, 0x06); + pincfg.bit.PULLEN = true; PINOP(HOLD_PIN, OUTSET); // Pin is pulled up. #elif defined(HOLD_PIN_PULLDOWN) - PINCFG(HOLD_PIN, 0x06); + pincfg.bit.PULLEN = true; PINOP(HOLD_PIN, OUTCLR); // Pin is pulled up. - #else - PINCFG(HOLD_PIN, 0x02); #endif + PINCFG(HOLD_PIN) = pincfg.reg; if (PINIP(HOLD_PIN) == HOLD_STATE) { /* Stay in bootloader */ From d6071d997355a5d18cf5214e3bae25b1742256ab Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Mon, 11 Jun 2018 12:39:28 +0800 Subject: [PATCH 4/5] Make PINCFG macro more flexible (can read or write) Add macro for updating PINMUX. --- inc/uf2.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/inc/uf2.h b/inc/uf2.h index 06b98d17..91c5c40b 100644 --- a/inc/uf2.h +++ b/inc/uf2.h @@ -244,7 +244,8 @@ void system_init(void); #define PINOP(pin, OP) (PORT->Group[(pin) / 32].OP.reg = (1 << ((pin) % 32))) #define PINIP(pin) (((PORT->Group[(pin) / 32].IN.reg) >> ((pin) % 32)) & 0x1) -#define PINCFG(pin, cfg) (PORT->Group[(pin) / 32].PINCFG[(pin) % 32].reg = cfg) +#define PINCFG(pin) (PORT->Group[(pin) / 32].PINCFG[(pin) % 32].reg) +#define PINMUX(pin) (PORT->Group[(pin) / 32].PMUX[((pin) % 32)/2].reg) void led_tick(void); void led_signal(void); From a714932ca51dbed8b543b2d23068a7417a1061ee Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Tue, 19 Jun 2018 11:23:10 +0800 Subject: [PATCH 5/5] Document the hold GPIO functionality --- README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/README.md b/README.md index 30a05a49..e59b0283 100644 --- a/README.md +++ b/README.md @@ -188,6 +188,30 @@ Thus, it's best to set the USB ID to one for which there are no drivers. The bootloader sits at 0x00000000, and the application starts at 0x00002000. +#### Bootloader Hold Switch + +A Board can be configured to sense the state of a GPIO and to hold the bootloader from running an application if it is in the appropriate state. To enable this, add the following to your board configuration header file. + +```C +// The Pin that will tell us to stay in the bootloader or not. +#define HOLD_PIN PIN_PA02 + +// Optional, define if a Pull up or pulldown is needed. +#define HOLD_PIN_PULLUP +//#define HOLD_PIN_PULLDOWN + +// What is the Hold state of the GPIO, 0 or 1. +#define HOLD_STATE 1 +``` + +Set `HOLD_PIN` to the appropriate GPIO and `HOLD_STATE` to the logic level which will hold the bootloader from running the application. + +The definition of _BOTH_ `HOLD_PIN` and `HOLD_STATE` triggers the inclusion of this feature. If either of these is undefined, this feature is not enabled. + +If an internal pullup/pulldown is required for the IO, it can be enabled with the _OPTIONAL_ `HOLD_PIN_PULLUP` or `HOLD_PIN_PULLDOWN` macros. If neither are defined, then no pullup/pulldown will be enabled for the io pin. + +This switch is NOT dynamic. Once the bootloader has sensed this pin and decided not to run the application, then a change in this IO will not, itself, then cause the Application to run, without also resetting the board. + ## Code of Conduct This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.