From cdd5e76add504614818d5c4d10c570a143311ff6 Mon Sep 17 00:00:00 2001 From: Daniel Thompson Date: Sat, 7 Nov 2020 09:26:59 +0000 Subject: [PATCH] Add code to wake spinor. Many PineTime payloads (currently including mcuboot) are broken if booted with the spinor in deep powerdown. Let's wake the spinor during reloading to avoid bugs when switching from a firmware with power down support to one without. The changes here are suprisingly large because we have to refactor the existing spi code to untangle it from the st7789 driver. Signed-off-by: Daniel Thompson --- .gitignore | 1 + Makefile | 2 ++ src/boards/pinetime/board.h | 3 ++ src/main.c | 15 ++++++++- src/spi.c | 64 +++++++++++++++++++++++++++++++++++++ src/spi.h | 15 +++++++++ src/spinor.c | 43 +++++++++++++++++++++++++ src/spinor.h | 17 ++++++++++ src/st7789.c | 64 ++++--------------------------------- src/st7789.h | 1 + 10 files changed, 167 insertions(+), 58 deletions(-) create mode 100644 src/spi.c create mode 100644 src/spi.h create mode 100644 src/spinor.c create mode 100644 src/spinor.h diff --git a/.gitignore b/.gitignore index 5738437..0a20975 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +.*.swp build-*/ src/boards/*/bootloader.h diff --git a/Makefile b/Makefile index ae9fe08..d9fe60d 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,8 @@ LDFLAGS += $(CFLAGS) -Wl,-Map=$(OBJDIR)/reloader.map -Lsrc -Llib/nrfx/mdk -T$(LD APP = $(OBJDIR)/reloader.zip OBJS = main.o \ flash.o \ + spi.o \ + spinor.o \ st7789.o \ wdt.o \ nrfx_nvmc.o \ diff --git a/src/boards/pinetime/board.h b/src/boards/pinetime/board.h index 0b5e536..f133553 100644 --- a/src/boards/pinetime/board.h +++ b/src/boards/pinetime/board.h @@ -15,4 +15,7 @@ #define CONFIG_WDT_BUTTON_PULL (0) // no pull up/down #define CONFIG_WDT_BUTTON_ENABLE (15) +#define CONFIG_HAVE_SPINOR (1) +#define CONFIG_SPINOR_CS (5) + #endif /* RELOADER_BOARD_PINETIME_H__ */ diff --git a/src/main.c b/src/main.c index f603098..b94730b 100644 --- a/src/main.c +++ b/src/main.c @@ -8,6 +8,8 @@ #include "board.h" #include "flash.h" +#include "spi.h" +#include "spinor.h" #include "st7789.h" #include "util.h" #include "wdt.h" @@ -44,10 +46,21 @@ int main() wdt_init(); #ifdef CONFIG_ST7789 - st7789_init(); + st7789_preinit(); #else nrf_gpio_cfg_output(CONFIG_USR_LED); #endif +#ifdef CONFIG_HAVE_SPINOR + spinor_preinit(); +#endif + + spi_init(); +#ifdef CONFIG_ST7789 + st7789_init(); +#endif +#ifdef CONFIG_HAVE_SPINOR + spinor_init(); +#endif flash_all(); reboot(); diff --git a/src/spi.c b/src/spi.c new file mode 100644 index 0000000..ec9c50f --- /dev/null +++ b/src/spi.c @@ -0,0 +1,64 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * Copyright (C) 2020 Daniel Thompson + */ + +#include "spi.h" + +#include +#include + +#define SPIx NRF_SPI0 +#define SPI_MODE NRF_SPI_MODE_3 +#define SPI_SCK 2 +#define SPI_MOSI 3 + +void spi_init(void) +{ + nrf_gpio_pin_write(SPI_SCK, SPI_MODE >= 2); + nrf_gpio_cfg(SPI_SCK, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_CONNECT, + NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_S0S1, NRF_GPIO_PIN_NOSENSE); + nrf_gpio_pin_clear(SPI_MOSI); + nrf_gpio_cfg_output(SPI_MOSI); + + + nrf_spi_pins_set(SPIx, SPI_SCK, SPI_MOSI, NRF_SPI_PIN_NOT_CONNECTED); + nrf_spi_frequency_set(SPIx, NRF_SPI_FREQ_8M); + nrf_spi_configure(SPIx, SPI_MODE, NRF_SPI_BIT_ORDER_MSB_FIRST); + + nrf_spi_enable(SPIx); +} + +void spi_teardown(void) +{ + /* no need to tear down SCK and MOSI - output pins can be left alone */ + nrf_spi_event_clear(SPIx, NRF_SPI_EVENT_READY); + nrf_spi_disable(SPIx); + nrf_gpio_cfg_default(SPI_MOSI); + nrf_gpio_cfg_default(SPI_SCK); +} + +void spi_write(const uint8_t *data, unsigned len) +{ + const uint8_t *endp = data + len; + + /* paranoid... but worthwhile due to the havoc this could cause */ + nrf_spi_event_clear(SPIx, NRF_SPI_EVENT_READY); + + /* send first character */ + nrf_spi_txd_set(SPIx, *data++); + + /* TXD is double buffers so we can xmit and then poll for the event */ + while (data < endp) { + nrf_spi_txd_set(SPIx, *data++); + + while (!nrf_spi_event_check(SPIx, NRF_SPI_EVENT_READY)) {} + nrf_spi_event_clear(SPIx, NRF_SPI_EVENT_READY); + (void) nrf_spi_rxd_get(SPIx); + } + + /* wait for the final character */ + while (!nrf_spi_event_check(SPIx, NRF_SPI_EVENT_READY)) {} + nrf_spi_event_clear(SPIx, NRF_SPI_EVENT_READY); + (void) nrf_spi_rxd_get(SPIx); +} diff --git a/src/spi.h b/src/spi.h new file mode 100644 index 0000000..04fc62c --- /dev/null +++ b/src/spi.h @@ -0,0 +1,15 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * Copyright (C) 2020 Daniel Thompson + */ + +#ifndef RELOADER_SPI_H__ +#define RELOADER_SPI_H__ + +#include + +void spi_init(void); +void spi_teardown(void); +void spi_write(const uint8_t *data, unsigned len); + +#endif /* RELOADER_SPI_H__ */ diff --git a/src/spinor.c b/src/spinor.c new file mode 100644 index 0000000..1a27ac6 --- /dev/null +++ b/src/spinor.c @@ -0,0 +1,43 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * Copyright (C) 2020 Daniel Thompson + */ + +#include "spinor.h" + +#include + +#include "board.h" +#include "spi.h" + +#ifdef CONFIG_HAVE_SPINOR + +uint32_t spinor_page_size_get(void) +{ + return 0; +} + +int spinor_page_erase(uint32_t addr) +{ + return -1; +} + +void spinor_word_write(uint32_t addr, uint32_t value) +{ +} + +void spinor_preinit(void) +{ + nrf_gpio_pin_set(CONFIG_SPINOR_CS); + nrf_gpio_cfg_output(CONFIG_SPINOR_CS); +} + +void spinor_init(void) +{ + /* release deep power-down (RDP) */ + nrf_gpio_pin_clear(CONFIG_SPINOR_CS); + spi_write((const uint8_t*) "\xab", 1); + nrf_gpio_pin_set(CONFIG_SPINOR_CS); +} + +#endif /* CONFIG_HAVE_SPINOR */ diff --git a/src/spinor.h b/src/spinor.h new file mode 100644 index 0000000..09ac6f4 --- /dev/null +++ b/src/spinor.h @@ -0,0 +1,17 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * Copyright (C) 2020 Daniel Thompson + */ + +#ifndef RELOADER_SPINOR_H__ +#define RELOADER_SPINOR_H__ + +#include + +uint32_t spinor_page_size_get(void); +int spinor_page_erase(uint32_t addr); +void spinor_word_write(uint32_t addr, uint32_t value); +void spinor_preinit(void); +void spinor_init(void); + +#endif /* RELOADER_SPINOR_H__ */ diff --git a/src/st7789.c b/src/st7789.c index 3c9a868..8c94cbe 100644 --- a/src/st7789.c +++ b/src/st7789.c @@ -3,77 +3,25 @@ * Copyright (C) 2020 Daniel Thompson */ +#include "st7789.h" + #include #include #include #include "board.h" -#include "st7789.h" +#include "spi.h" #ifndef CONFIG_ST7789_BACKLIGHT #define CONFIG_ST7789_BACKLIGHT 14 #endif -#define SPIx NRF_SPI0 -#define SPI_MODE NRF_SPI_MODE_3 -#define SPI_SCK 2 -#define SPI_MOSI 3 #define DISP_SS 25 #define DISP_DC 18 #define DISP_RESET 26 #define BACKLIGHT CONFIG_ST7789_BACKLIGHT /* lowest level */ -static void spi_init(void) -{ - nrf_gpio_pin_write(SPI_SCK, SPI_MODE >= 2); - nrf_gpio_cfg(SPI_SCK, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_CONNECT, - NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_S0S1, NRF_GPIO_PIN_NOSENSE); - nrf_gpio_pin_clear(SPI_MOSI); - nrf_gpio_cfg_output(SPI_MOSI); - - - nrf_spi_pins_set(SPIx, SPI_SCK, SPI_MOSI, NRF_SPI_PIN_NOT_CONNECTED); - nrf_spi_frequency_set(SPIx, NRF_SPI_FREQ_8M); - nrf_spi_configure(SPIx, SPI_MODE, NRF_SPI_BIT_ORDER_MSB_FIRST); - - nrf_spi_enable(SPIx); -} - -static void spi_teardown(void) -{ - /* no need to tear down SCK and MOSI - output pins can be left alone */ - nrf_spi_event_clear(SPIx, NRF_SPI_EVENT_READY); - nrf_spi_disable(SPIx); - nrf_gpio_cfg_default(SPI_MOSI); - nrf_gpio_cfg_default(SPI_SCK); -} - -static void spi_write(const uint8_t *data, unsigned len) -{ - const uint8_t *endp = data + len; - - /* paranoid... but worthwhile due to the havoc this could cause */ - nrf_spi_event_clear(SPIx, NRF_SPI_EVENT_READY); - - /* send first character */ - nrf_spi_txd_set(SPIx, *data++); - - /* TXD is double buffers so we can xmit and then poll for the event */ - while (data < endp) { - nrf_spi_txd_set(SPIx, *data++); - - while (!nrf_spi_event_check(SPIx, NRF_SPI_EVENT_READY)) {} - nrf_spi_event_clear(SPIx, NRF_SPI_EVENT_READY); - (void) nrf_spi_rxd_get(SPIx); - } - - /* wait for the final character */ - while (!nrf_spi_event_check(SPIx, NRF_SPI_EVENT_READY)) {} - nrf_spi_event_clear(SPIx, NRF_SPI_EVENT_READY); - (void) nrf_spi_rxd_get(SPIx); -} - #define NOP 0x00 #define SWRESET 0x01 #define SLPOUT 0x11 @@ -276,12 +224,14 @@ void st7789_state(int percent_complete) } } -void st7789_init(void) +void st7789_preinit(void) { nrf_gpio_pin_set(DISP_SS); nrf_gpio_cfg_output(DISP_SS); - spi_init(); +} +void st7789_init(void) +{ nrf_gpio_cfg_output(DISP_DC); /* deliver a reset */ diff --git a/src/st7789.h b/src/st7789.h index b23f62e..5db47b8 100644 --- a/src/st7789.h +++ b/src/st7789.h @@ -13,6 +13,7 @@ enum { }; void st7789_state(int state); +void st7789_preinit(void); void st7789_init(void); void st7789_teardown(void);