@@ -93,6 +93,33 @@ static ram_func void flash_enable_xip_via_boot2() {
9393 ((void (*)(void))boot2_copyout+1)();
9494}
9595
96+ #define IO_QSPI_BASE 0x40018000
97+ #define IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_BITS 0x00000300
98+ #define IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_MSB 9
99+ #define IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_LSB 8
100+ #define IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_VALUE_LOW 0x2
101+ #define IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_VALUE_HIGH 0x3
102+
103+ #define XIP_SSI_BASE 0x18000000
104+ #define ssi_hw ((ssi_hw_t *)XIP_SSI_BASE)
105+ #define SSI_SR_OFFSET 0x00000028
106+ #define SSI_DR0_OFFSET 0x00000060
107+ #define SSI_SR_TFNF_BITS 0x00000002
108+ #define SSI_SR_RFNE_BITS 0x00000008
109+
110+ void ram_func flash_cs_force(bool high) {
111+ uint32_t field_val = high ?
112+ IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_VALUE_HIGH :
113+ IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_VALUE_LOW;
114+
115+ // &ioqspi_hw->io[1].ctrl
116+ uint32_t *addr = (uint32_t*)(IO_QSPI_BASE + (1 * 8) + 4);
117+
118+ *addr = ((*addr) & !IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_BITS)
119+ | (field_val << IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_LSB);
120+
121+ }
122+
96123// See https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_flash/flash.c#L86
97124void ram_func flash_range_write(uint32_t offset, const uint8_t *data, size_t count)
98125{
@@ -132,13 +159,62 @@ void ram_func flash_erase_blocks(uint32_t offset, size_t count)
132159 flash_enable_xip_via_boot2();
133160}
134161
162+ void ram_func flash_do_cmd(const uint8_t *txbuf, uint8_t *rxbuf, size_t count) {
163+ flash_connect_internal_fn flash_connect_internal_func = (flash_connect_internal_fn) rom_func_lookup(ROM_FUNC_CONNECT_INTERNAL_FLASH);
164+ flash_exit_xip_fn flash_exit_xip_func = (flash_exit_xip_fn) rom_func_lookup(ROM_FUNC_FLASH_EXIT_XIP);
165+ flash_flush_cache_fn flash_flush_cache_func = (flash_flush_cache_fn) rom_func_lookup(ROM_FUNC_FLASH_FLUSH_CACHE);
166+
167+ flash_init_boot2_copyout();
168+
169+ __compiler_memory_barrier();
170+
171+ flash_connect_internal_func();
172+ flash_exit_xip_func();
173+
174+ flash_cs_force(0);
175+ size_t tx_remaining = count;
176+ size_t rx_remaining = count;
177+ // We may be interrupted -- don't want FIFO to overflow if we're distracted.
178+ const size_t max_in_flight = 16 - 2;
179+ while (tx_remaining || rx_remaining) {
180+ uint32_t flags = *(uint32_t*)(XIP_SSI_BASE + SSI_SR_OFFSET);
181+ bool can_put = !!(flags & SSI_SR_TFNF_BITS);
182+ bool can_get = !!(flags & SSI_SR_RFNE_BITS);
183+ if (can_put && tx_remaining && rx_remaining - tx_remaining < max_in_flight) {
184+ *(uint32_t*)(XIP_SSI_BASE + SSI_DR0_OFFSET) = *txbuf++;
185+ --tx_remaining;
186+ }
187+ if (can_get && rx_remaining) {
188+ *rxbuf++ = (uint8_t)*(uint32_t*)(XIP_SSI_BASE + SSI_DR0_OFFSET);
189+ --rx_remaining;
190+ }
191+ }
192+ flash_cs_force(1);
193+
194+ flash_flush_cache_func();
195+ flash_enable_xip_via_boot2();
196+ }
197+
135198*/
136199import "C"
137200
138201func enterBootloader () {
139202 C .reset_usb_boot (0 , 0 )
140203}
141204
205+ func doFlashCommand (tx []byte , rx []byte ) error {
206+ if len (tx ) != len (rx ) {
207+ return errFlashInvalidWriteLength
208+ }
209+
210+ C .flash_do_cmd (
211+ (* C .uint8_t )(unsafe .Pointer (& tx [0 ])),
212+ (* C .uint8_t )(unsafe .Pointer (& rx [0 ])),
213+ C .ulong (len (tx )))
214+
215+ return nil
216+ }
217+
142218// Flash related code
143219const memoryStart = C .XIP_BASE // memory start for purpose of erase
144220
0 commit comments