3838#include "supervisor/shared/external_flash/common_commands.h"
3939#include "supervisor/shared/external_flash/qspi_flash.h"
4040
41+ // When USB is disconnected, disable QSPI in sleep mode to save energy
42+ void qspi_disable (void )
43+ {
44+ // If VBUS is detected, no need to disable QSPI
45+ if (NRF_QSPI -> ENABLE && !(NRF_POWER -> USBREGSTATUS & POWER_USBREGSTATUS_VBUSDETECT_Msk )) {
46+ // Keep CS high when QSPI is diabled
47+ nrf_gpio_cfg_output (MICROPY_QSPI_CS );
48+ nrf_gpio_pin_write (MICROPY_QSPI_CS , 1 );
49+
50+ // Workaround to disable QSPI according to nRF52840 Revision 1 Errata V1.4 - 3.8
51+ NRF_QSPI -> TASKS_DEACTIVATE = 1 ;
52+ * (volatile uint32_t * )0x40029054 = 1 ;
53+ NRF_QSPI -> ENABLE = 0 ;
54+ }
55+ }
56+
57+ void qspi_enable (void )
58+ {
59+ if (NRF_QSPI -> ENABLE ) {
60+ return ;
61+ }
62+
63+ nrf_qspi_enable (NRF_QSPI );
64+
65+ nrf_qspi_event_clear (NRF_QSPI , NRF_QSPI_EVENT_READY );
66+ nrf_qspi_task_trigger (NRF_QSPI , NRF_QSPI_TASK_ACTIVATE );
67+
68+ uint32_t remaining_attempts = 100 ;
69+ do {
70+ if (nrf_qspi_event_check (NRF_QSPI , NRF_QSPI_EVENT_READY )) {
71+ break ;
72+ }
73+ NRFX_DELAY_US (10 );
74+ } while (-- remaining_attempts );
75+ }
76+
4177bool spi_flash_command (uint8_t command ) {
78+ qspi_enable ();
4279 nrf_qspi_cinstr_conf_t cinstr_cfg = {
4380 .opcode = command ,
4481 .length = 1 ,
@@ -51,6 +88,7 @@ bool spi_flash_command(uint8_t command) {
5188}
5289
5390bool spi_flash_read_command (uint8_t command , uint8_t * response , uint32_t length ) {
91+ qspi_enable ();
5492 nrf_qspi_cinstr_conf_t cinstr_cfg = {
5593 .opcode = command ,
5694 .length = length + 1 ,
@@ -64,6 +102,7 @@ bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length)
64102}
65103
66104bool spi_flash_write_command (uint8_t command , uint8_t * data , uint32_t length ) {
105+ qspi_enable ();
67106 nrf_qspi_cinstr_conf_t cinstr_cfg = {
68107 .opcode = command ,
69108 .length = length + 1 ,
@@ -76,20 +115,23 @@ bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) {
76115}
77116
78117bool spi_flash_sector_command (uint8_t command , uint32_t address ) {
118+ qspi_enable ();
79119 if (command != CMD_SECTOR_ERASE ) {
80120 return false;
81121 }
82122 return nrfx_qspi_erase (NRF_QSPI_ERASE_LEN_4KB , address ) == NRFX_SUCCESS ;
83123}
84124
85125bool spi_flash_write_data (uint32_t address , uint8_t * data , uint32_t length ) {
126+ qspi_enable ();
86127 // TODO: In theory, this also needs to handle unaligned data and
87128 // non-multiple-of-4 length. (in practice, I don't think the fat layer
88129 // generates such writes)
89130 return nrfx_qspi_write (data , length , address ) == NRFX_SUCCESS ;
90131}
91132
92133bool spi_flash_read_data (uint32_t address , uint8_t * data , uint32_t length ) {
134+ qspi_enable ();
93135 int misaligned = ((intptr_t )data ) & 3 ;
94136 // If the data is misaligned, we need to read 4 bytes
95137 // into an aligned buffer, and then copy 1, 2, or 3 bytes from the aligned
0 commit comments