Our system was running out of external peripherals and we decided to switch over the external SPI NOR flash to a bit bang driver however this resulted in odd behaviour when the old bootloader was still running with SPI3 and the application with the bitbang SPI.
The main cause was that when the bootloader used the external flash (On SPI3) it configured the PSEL pins in SPI operation mode which connected the appropriate GPIO pins to the MISO MOSI and SCK pins.
However the application image hereafter used the same hardware periphiral in uart mode (UART3) and properly configured the TXD and RXD pins, however the SPI3->PSEL->SCK register overlaps with the UART3->PSEL->RTS register and this register isn't explicitly set to disconnected on UART3 initialization when no flow control is specified. This means that UART3 got initialized with stale SPI3 configuration values during boot loader application hand-off, even with the KCONFIG option CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL set.
This resulted the Bit-bang driver unable to drive the SCK pin (Overwritten by UART3) but the GPIO set functions didn't return error codes and acted like the clock was being properly asserted, so all data read from the external flash was 0x00 without any error codes.
This problem can be fixed by changing the UART3 pin control to explicitly disconnect the CTS and RTS lines instead of leaving them undefined:
Doesnt work and uses stale values:
uart_solar_default: uart_solar_default { group1 { psels = <NRF_PSEL(UART_TX, 0, 11)>, <NRF_PSEL(UART_RX, 0, 12)>, }; };
Works by explicitly setting pins to disconnected:
uart_solar_default: uart_solar_default { group1 { psels = <NRF_PSEL(UART_TX, 0, 11)>, <NRF_PSEL(UART_RX, 0, 12)>, <NRF_PSEL_DISCONNECTED(UART_CTS)>, <NRF_PSEL_DISCONNECTED(UART_RTS)>; }; };
The documentation here: Documentation does specify that all relevant registers should be explicitly set but this seems like it should be done by the UART driver when no CTS or RTS pins are set. Also the CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL option sounds like it should clean all the peripherals to a reset state however it only disconnects all DPPIC channels, clears the RTC's and disconnects UART0 and UART1.
We tried looking trough the documentation but there isn't a mention on MCUboot or Bootloader documentation that warns for Stale peripheral registers and since the application code shouldn't be dependent or borked by stale bootloader leftovers we think its important to have this highlighted somewhere.
We used version 2.6 of the NRF SDK