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
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
+
41
77
bool spi_flash_command (uint8_t command ) {
78
+ qspi_enable ();
42
79
nrf_qspi_cinstr_conf_t cinstr_cfg = {
43
80
.opcode = command ,
44
81
.length = 1 ,
@@ -51,6 +88,7 @@ bool spi_flash_command(uint8_t command) {
51
88
}
52
89
53
90
bool spi_flash_read_command (uint8_t command , uint8_t * response , uint32_t length ) {
91
+ qspi_enable ();
54
92
nrf_qspi_cinstr_conf_t cinstr_cfg = {
55
93
.opcode = command ,
56
94
.length = length + 1 ,
@@ -64,6 +102,7 @@ bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length)
64
102
}
65
103
66
104
bool spi_flash_write_command (uint8_t command , uint8_t * data , uint32_t length ) {
105
+ qspi_enable ();
67
106
nrf_qspi_cinstr_conf_t cinstr_cfg = {
68
107
.opcode = command ,
69
108
.length = length + 1 ,
@@ -76,20 +115,23 @@ bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) {
76
115
}
77
116
78
117
bool spi_flash_sector_command (uint8_t command , uint32_t address ) {
118
+ qspi_enable ();
79
119
if (command != CMD_SECTOR_ERASE ) {
80
120
return false;
81
121
}
82
122
return nrfx_qspi_erase (NRF_QSPI_ERASE_LEN_4KB , address ) == NRFX_SUCCESS ;
83
123
}
84
124
85
125
bool spi_flash_write_data (uint32_t address , uint8_t * data , uint32_t length ) {
126
+ qspi_enable ();
86
127
// TODO: In theory, this also needs to handle unaligned data and
87
128
// non-multiple-of-4 length. (in practice, I don't think the fat layer
88
129
// generates such writes)
89
130
return nrfx_qspi_write (data , length , address ) == NRFX_SUCCESS ;
90
131
}
91
132
92
133
bool spi_flash_read_data (uint32_t address , uint8_t * data , uint32_t length ) {
134
+ qspi_enable ();
93
135
int misaligned = ((intptr_t )data ) & 3 ;
94
136
// If the data is misaligned, we need to read 4 bytes
95
137
// into an aligned buffer, and then copy 1, 2, or 3 bytes from the aligned
0 commit comments