38
38
#include "supervisor/shared/external_flash/common_commands.h"
39
39
#include "supervisor/shared/external_flash/qspi_flash.h"
40
40
41
+ // When USB is disconnected, disable QSPI in sleep mode to save energy
41
42
#if defined(MICROPY_QSPI_OFF_WHEN_SLEEP )
42
- #define QSPI_ENABLE () qspi_enable()
43
-
44
- static void qspi_enable (void )
43
+ void qspi_enable (void )
45
44
{
46
45
if (NRF_QSPI -> ENABLE ) {
47
46
return ;
@@ -61,12 +60,32 @@ static void qspi_enable(void)
61
60
} while (-- remaining_attempts );
62
61
}
63
62
63
+ void qspi_disable (void )
64
+ {
65
+ // Turn off QSPI when USB is disconnected
66
+ if (NRF_QSPI -> ENABLE && !(NRF_POWER -> USBREGSTATUS & POWER_USBREGSTATUS_VBUSDETECT_Msk )) {
67
+ // Keep CS high when QSPI is diabled
68
+ nrf_gpio_cfg_output (MICROPY_QSPI_CS );
69
+ nrf_gpio_pin_write (MICROPY_QSPI_CS , 1 );
70
+
71
+ // Workaround to disable QSPI according to nRF52840 Revision 1 Errata V1.4 - 3.8
72
+ NRF_QSPI -> TASKS_DEACTIVATE = 1 ;
73
+ * (volatile uint32_t * )0x40029054 = 1 ;
74
+ NRF_QSPI -> ENABLE = 0 ;
75
+ }
76
+ }
64
77
#else
65
- #define QSPI_ENABLE () ((void)0)
78
+ void qspi_enable (void )
79
+ {
80
+ }
81
+
82
+ void qspi_disable (void )
83
+ {
84
+ }
66
85
#endif
67
86
68
87
bool spi_flash_command (uint8_t command ) {
69
- QSPI_ENABLE ();
88
+ qspi_enable ();
70
89
nrf_qspi_cinstr_conf_t cinstr_cfg = {
71
90
.opcode = command ,
72
91
.length = 1 ,
@@ -79,7 +98,7 @@ bool spi_flash_command(uint8_t command) {
79
98
}
80
99
81
100
bool spi_flash_read_command (uint8_t command , uint8_t * response , uint32_t length ) {
82
- QSPI_ENABLE ();
101
+ qspi_enable ();
83
102
nrf_qspi_cinstr_conf_t cinstr_cfg = {
84
103
.opcode = command ,
85
104
.length = length + 1 ,
@@ -93,7 +112,7 @@ bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length)
93
112
}
94
113
95
114
bool spi_flash_write_command (uint8_t command , uint8_t * data , uint32_t length ) {
96
- QSPI_ENABLE ();
115
+ qspi_enable ();
97
116
nrf_qspi_cinstr_conf_t cinstr_cfg = {
98
117
.opcode = command ,
99
118
.length = length + 1 ,
@@ -106,23 +125,23 @@ bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) {
106
125
}
107
126
108
127
bool spi_flash_sector_command (uint8_t command , uint32_t address ) {
109
- QSPI_ENABLE ();
128
+ qspi_enable ();
110
129
if (command != CMD_SECTOR_ERASE ) {
111
130
return false;
112
131
}
113
132
return nrfx_qspi_erase (NRF_QSPI_ERASE_LEN_4KB , address ) == NRFX_SUCCESS ;
114
133
}
115
134
116
135
bool spi_flash_write_data (uint32_t address , uint8_t * data , uint32_t length ) {
117
- QSPI_ENABLE ();
136
+ qspi_enable ();
118
137
// TODO: In theory, this also needs to handle unaligned data and
119
138
// non-multiple-of-4 length. (in practice, I don't think the fat layer
120
139
// generates such writes)
121
140
return nrfx_qspi_write (data , length , address ) == NRFX_SUCCESS ;
122
141
}
123
142
124
143
bool spi_flash_read_data (uint32_t address , uint8_t * data , uint32_t length ) {
125
- QSPI_ENABLE ();
144
+ qspi_enable ();
126
145
int misaligned = ((intptr_t )data ) & 3 ;
127
146
// If the data is misaligned, we need to read 4 bytes
128
147
// into an aligned buffer, and then copy 1, 2, or 3 bytes from the aligned
0 commit comments