-
-
Notifications
You must be signed in to change notification settings - Fork 785
/
Copy pathrp2040.c
731 lines (654 loc) · 29.6 KB
/
rp2040.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2021 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
* Copyright (C) 2022-2023 1BitSquared <info@1bitsquared.com>
* Significantly rewritten in 2022 by Rachel Mant <git@dragonmux.network>
* Copyright (C) 2022 James Turton
* Includes extracts from pico-bootrom
* Copyright (C) 2020 Raspberry Pi (Trading) Ltd
* Modified by Rachel Mant <git@dragonmux.network>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* This file implements Raspberry Pico (RP2040) target specific functions
* for detecting the device, providing the XML memory map and
* Flash memory programming.
*/
#include "general.h"
#include "target.h"
#include "target_internal.h"
#include "cortexm.h"
#include "spi.h"
#include "sfdp.h"
#define RP_MAX_TABLE_SIZE 0x80U
#define BOOTROM_MAGIC_ADDR 0x00000010U
#define BOOTROM_MAGIC ((uint32_t)'M' | ((uint32_t)'u' << 8U) | (1U << 16U))
#define BOOTROM_MAGIC_MASK 0x00ffffffU
#define BOOTROM_VERSION_SHIFT 24U
#define RP_XIP_FLASH_BASE 0x10000000U
#define RP_SRAM_BASE 0x20000000U
#define RP_SRAM_SIZE 0x42000U
#define RP_STUB_BUFFER_BASE (RP_SRAM_BASE + 0x1000)
#define RP_REG_ACCESS_NORMAL 0x0000U
#define RP_REG_ACCESS_WRITE_XOR 0x1000U
#define RP_REG_ACCESS_WRITE_ATOMIC_BITSET 0x2000U
#define RP_REG_ACCESS_WRITE_ATOMIC_BITCLR 0x3000U
#define RP_CLOCKS_BASE_ADDR 0x40008000U
#define RP_CLOCKS_WAKE_EN0 (RP_CLOCKS_BASE_ADDR + 0xa0U)
#define RP_CLOCKS_WAKE_EN1 (RP_CLOCKS_BASE_ADDR + 0xa4U)
#define RP_CLOCKS_WAKE_EN0_MASK 0xff0c0f19U
#define RP_CLOCKS_WAKE_EN1_MASK 0x00002007U
#define RP_GPIO_QSPI_BASE_ADDR 0x40018000U
#define RP_GPIO_QSPI_SCLK_CTRL (RP_GPIO_QSPI_BASE_ADDR + 0x04U)
#define RP_GPIO_QSPI_CS_CTRL (RP_GPIO_QSPI_BASE_ADDR + 0x0cU)
#define RP_GPIO_QSPI_SD0_CTRL (RP_GPIO_QSPI_BASE_ADDR + 0x14U)
#define RP_GPIO_QSPI_SD1_CTRL (RP_GPIO_QSPI_BASE_ADDR + 0x1cU)
#define RP_GPIO_QSPI_SD2_CTRL (RP_GPIO_QSPI_BASE_ADDR + 0x24U)
#define RP_GPIO_QSPI_SD3_CTRL (RP_GPIO_QSPI_BASE_ADDR + 0x2cU)
#define RP_GPIO_QSPI_CS_DRIVE_NORMAL (0U << 8U)
#define RP_GPIO_QSPI_CS_DRIVE_INVERT (1U << 8U)
#define RP_GPIO_QSPI_CS_DRIVE_LOW (2U << 8U)
#define RP_GPIO_QSPI_CS_DRIVE_HIGH (3U << 8U)
#define RP_GPIO_QSPI_CS_DRIVE_MASK 0x00000300U
#define RP_GPIO_QSPI_SD1_CTRL_INOVER_BITS 0x00030000U
#define RP_GPIO_QSPI_SCLK_POR 0x0000001fU
#define RP_SSI_BASE_ADDR 0x18000000U
#define RP_SSI_CTRL0 (RP_SSI_BASE_ADDR + 0x00U)
#define RP_SSI_CTRL1 (RP_SSI_BASE_ADDR + 0x04U)
#define RP_SSI_ENABLE (RP_SSI_BASE_ADDR + 0x08U)
#define RP_SSI_SER (RP_SSI_BASE_ADDR + 0x10U)
#define RP_SSI_BAUD (RP_SSI_BASE_ADDR + 0x14U)
#define RP_SSI_TXFLR (RP_SSI_BASE_ADDR + 0x20U)
#define RP_SSI_RXFLR (RP_SSI_BASE_ADDR + 0x24U)
#define RP_SSI_SR (RP_SSI_BASE_ADDR + 0x28U)
#define RP_SSI_ICR (RP_SSI_BASE_ADDR + 0x48U)
#define RP_SSI_DR0 (RP_SSI_BASE_ADDR + 0x60U)
#define RP_SSI_XIP_SPI_CTRL0 (RP_SSI_BASE_ADDR + 0xf4U)
#define RP_SSI_CTRL0_FRF_MASK 0x00600000U
#define RP_SSI_CTRL0_FRF_SERIAL (0U << 21U)
#define RP_SSI_CTRL0_FRF_DUAL (1U << 21U)
#define RP_SSI_CTRL0_FRF_QUAD (2U << 21U)
#define RP_SSI_CTRL0_TMOD_MASK 0x00000300U
#define RP_SSI_CTRL0_TMOD_BIDI (0U << 8U)
#define RP_SSI_CTRL0_TMOD_TX_ONLY (1U << 8U)
#define RP_SSI_CTRL0_TMOD_RX_ONLY (2U << 8U)
#define RP_SSI_CTRL0_TMOD_EEPROM (3U << 8U)
#define RP_SSI_CTRL0_DATA_BIT_MASK 0x001f0000U
#define RP_SSI_CTRL0_DATA_BIT_SHIFT 16U
#define RP_SSI_CTRL0_DATA_BITS(x) (((x)-1U) << RP_SSI_CTRL0_DATA_BIT_SHIFT)
#define RP_SSI_CTRL0_MASK (RP_SSI_CTRL0_FRF_MASK | RP_SSI_CTRL0_TMOD_MASK | RP_SSI_CTRL0_DATA_BIT_MASK)
#define RP_SSI_ENABLE_SSI (1U << 0U)
#define RP_SSI_XIP_SPI_CTRL0_FORMAT_STD_SPI (0U << 0U)
#define RP_SSI_XIP_SPI_CTRL0_FORMAT_SPLIT (1U << 0U)
#define RP_SSI_XIP_SPI_CTRL0_FORMAT_FRF (2U << 0U)
#define RP_SSI_XIP_SPI_CTRL0_ADDRESS_LENGTH(x) (((x)*2U) << 2U)
#define RP_SSI_XIP_SPI_CTRL0_INSTR_LENGTH_8b (2U << 8U)
#define RP_SSI_XIP_SPI_CTRL0_WAIT_CYCLES(x) (((x)*8U) << 11U)
#define RP_SSI_XIP_SPI_CTRL0_XIP_CMD_SHIFT 24U
#define RP_SSI_XIP_SPI_CTRL0_XIP_CMD(x) ((x) << RP_SSI_XIP_SPI_CTRL0_XIP_CMD_SHIFT)
#define RP_SSI_XIP_SPI_CTRL0_TRANS_1C1A (0U << 0U)
#define RP_SSI_XIP_SPI_CTRL0_TRANS_1C2A (1U << 0U)
#define RP_SSI_XIP_SPI_CTRL0_TRANS_2C2A (2U << 0U)
#define RP_PADS_QSPI_BASE_ADDR 0x40020000U
#define RP_PADS_QSPI_GPIO_SCLK (RP_PADS_QSPI_BASE_ADDR + 0x04U)
#define RP_PADS_QSPI_GPIO_SD0 (RP_PADS_QSPI_BASE_ADDR + 0x08U)
#define RP_PADS_QSPI_GPIO_SD1 (RP_PADS_QSPI_BASE_ADDR + 0x0cU)
#define RP_PADS_QSPI_GPIO_SD2 (RP_PADS_QSPI_BASE_ADDR + 0x10U)
#define RP_PADS_QSPI_GPIO_SD3 (RP_PADS_QSPI_BASE_ADDR + 0x14U)
#define RP_PADS_QSPI_GPIO_SCLK_FAST_SLEW 0x00000001U
#define RP_PADS_QSPI_GPIO_SCLK_8mA_DRIVE 0x00000020U
#define RP_PADS_QSPI_GPIO_SCLK_IE 0x00000040U
#define RP_PADS_QSPI_GPIO_SD0_OD_BITS 0x00000080U
#define RP_PADS_QSPI_GPIO_SD0_PUE_BITS 0x00000008U
#define RP_PADS_QSPI_GPIO_SD0_PDE_BITS 0x00000004U
#define RP_XIP_BASE_ADDR 0x14000000U
#define RP_XIP_CTRL (RP_XIP_BASE_ADDR + 0x00U)
#define RP_XIP_FLUSH (RP_XIP_BASE_ADDR + 0x04U)
#define RP_XIP_STAT (RP_XIP_BASE_ADDR + 0x08U)
#define RP_XIP_CTRL_ENABLE 0x00000001U
#define RP_XIP_STAT_POR 0x00000002U
#define RP_RESETS_BASE_ADDR 0x4000c000U
#define RP_RESETS_RESET (RP_RESETS_BASE_ADDR + 0x00U)
#define RP_RESETS_RESET_DONE (RP_RESETS_BASE_ADDR + 0x08U)
#define RP_RESETS_RESET_IO_QSPI_BITS 0x00000040U
#define RP_RESETS_RESET_PADS_QSPI_BITS 0x00000200U
#define BOOTROM_FUNC_TABLE_ADDR 0x00000014U
#define BOOTROM_FUNC_TABLE_TAG(x, y) ((uint8_t)(x) | ((uint8_t)(y) << 8U))
#define FLASHSIZE_4K_SECTOR (4U * 1024U)
#define FLASHSIZE_32K_BLOCK (32U * 1024U)
#define FLASHSIZE_64K_BLOCK (64U * 1024U)
#define FLASHSIZE_32K_BLOCK_MASK ~(FLASHSIZE_32K_BLOCK - 1U)
#define FLASHSIZE_64K_BLOCK_MASK ~(FLASHSIZE_64K_BLOCK - 1U)
#define MAX_FLASH (16U * 1024U * 1024U)
#define MAX_WRITE_CHUNK 0x1000U
#define ID_RP2040 0x1002U
typedef struct rp_priv {
uint16_t rom_reset_usb_boot;
uint32_t ssi_enabled;
uint32_t ctrl0;
uint32_t ctrl1;
uint32_t xpi_ctrl0;
} rp_priv_s;
static bool rp_cmd_erase_sector(target_s *target, int argc, const char **argv);
static bool rp_cmd_reset_usb_boot(target_s *target, int argc, const char **argv);
const command_s rp_cmd_list[] = {
{"erase_sector", rp_cmd_erase_sector, "Erase a sector: [start address] length"},
{"reset_usb_boot", rp_cmd_reset_usb_boot, "Reboot the device into BOOTSEL mode"},
{NULL, NULL, NULL},
};
static const uint16_t rp_flash_write_stub[] = {
#include "flashstub/rp.stub"
};
static bool rp_read_rom_func_table(target_s *target);
static bool rp_attach(target_s *target);
static void rp_spi_config(target_s *target);
static void rp_spi_restore(target_s *target);
static bool rp_flash_prepare(target_s *target);
static bool rp_flash_resume(target_s *target);
static bool rp_flash_write(target_flash_s *flash, target_addr_t dest, const void *src, size_t length);
static void rp_spi_read(target_s *target, uint16_t command, target_addr32_t address, void *buffer, size_t length);
static void rp_spi_run_command(target_s *target, uint16_t command, target_addr32_t address);
static uint32_t rp_get_flash_length(target_s *target);
static bool rp_flash_in_por_state(target_s *target);
// Our own implementation of bootloader functions for handling flash chip
static void rp_flash_exit_xip(target_s *target);
static void rp_flash_enter_xip(target_s *target);
static void rp_flash_connect_internal(target_s *target);
static void rp_flash_flush_cache(target_s *target);
static void rp_add_flash(target_s *target)
{
const bool por_state = rp_flash_in_por_state(target);
DEBUG_INFO("RP2040 Flash controller %sin POR state, reconfiguring\n", por_state ? "" : "not ");
if (por_state)
rp_flash_connect_internal(target);
rp_flash_exit_xip(target);
rp_spi_config(target);
spi_flash_s *flash = bmp_spi_add_flash(
target, RP_XIP_FLASH_BASE, rp_get_flash_length(target), rp_spi_read, NULL, rp_spi_run_command);
flash->flash.write = rp_flash_write;
rp_spi_restore(target);
if (por_state)
rp_flash_flush_cache(target);
rp_flash_enter_xip(target);
}
bool rp2040_probe(target_s *const target)
{
/* Check that the target has the right part number */
if (target->part_id != ID_RP2040)
return false;
/* Check bootrom magic*/
uint32_t boot_magic = target_mem32_read32(target, BOOTROM_MAGIC_ADDR);
if ((boot_magic & BOOTROM_MAGIC_MASK) != BOOTROM_MAGIC) {
DEBUG_ERROR("Wrong Bootmagic %08" PRIx32 " found!\n", boot_magic);
return false;
}
#if ENABLE_DEBUG == 1
if ((boot_magic >> BOOTROM_VERSION_SHIFT) == 1)
DEBUG_WARN("Old Bootrom Version 1!\n");
#endif
rp_priv_s *priv_storage = calloc(1, sizeof(rp_priv_s));
if (!priv_storage) { /* calloc failed: heap exhaustion */
DEBUG_ERROR("calloc: failed in %s\n", __func__);
return false;
}
target->target_storage = (void *)priv_storage;
target->driver = "RP2040";
target->target_options |= TOPT_INHIBIT_NRST;
target->attach = rp_attach;
target->enter_flash_mode = rp_flash_prepare;
target->exit_flash_mode = rp_flash_resume;
target_add_commands(target, rp_cmd_list, target->driver);
return true;
}
static bool rp_attach(target_s *target)
{
if (!cortexm_attach(target) || !rp_read_rom_func_table(target))
return false;
/* Free previously loaded memory map */
target_mem_map_free(target);
rp_add_flash(target);
target_add_ram32(target, RP_SRAM_BASE, RP_SRAM_SIZE);
return true;
}
/*
* Parse out the ROM function table for routines we need.
* Entries in the table are in pairs of 16-bit integers:
* * A two character tag for the routine (see section 2.8.3 of the datasheet)
* * The 16-bit pointer associated with that routine
*/
static bool rp_read_rom_func_table(target_s *const target)
{
rp_priv_s *const priv = (rp_priv_s *)target->target_storage;
/* We have to do a 32-bit read here but the pointer contained is only 16-bit. */
const uint16_t table_offset = target_mem32_read32(target, BOOTROM_FUNC_TABLE_ADDR) & 0x0000ffffU;
uint16_t table[RP_MAX_TABLE_SIZE];
if (target_mem32_read(target, table, table_offset, RP_MAX_TABLE_SIZE))
return false;
for (size_t i = 0; i < RP_MAX_TABLE_SIZE; i += 2U) {
const uint16_t tag = table[i];
const uint16_t addr = table[i + 1U];
if (tag == BOOTROM_FUNC_TABLE_TAG('U', 'B')) {
priv->rom_reset_usb_boot = addr;
return true;
}
}
return false;
}
static void rp_spi_config(target_s *const target)
{
rp_priv_s *const priv = (rp_priv_s *)target->target_storage;
/* Ensure the controller is in the correct serial SPI mode */
priv->ssi_enabled = target_mem32_read32(target, RP_SSI_ENABLE);
target_mem32_write32(target, RP_SSI_ENABLE, 0);
priv->ctrl0 = target_mem32_read32(target, RP_SSI_CTRL0);
priv->ctrl1 = target_mem32_read32(target, RP_SSI_CTRL1);
priv->xpi_ctrl0 = target_mem32_read32(target, RP_SSI_XIP_SPI_CTRL0);
target_mem32_write32(target, RP_SSI_CTRL0,
(priv->ctrl0 & RP_SSI_CTRL0_MASK) | RP_SSI_CTRL0_FRF_SERIAL | RP_SSI_CTRL0_TMOD_BIDI |
RP_SSI_CTRL0_DATA_BITS(8));
target_mem32_write32(target, RP_SSI_XIP_SPI_CTRL0,
RP_SSI_XIP_SPI_CTRL0_FORMAT_FRF | RP_SSI_XIP_SPI_CTRL0_ADDRESS_LENGTH(0) |
RP_SSI_XIP_SPI_CTRL0_INSTR_LENGTH_8b | RP_SSI_XIP_SPI_CTRL0_WAIT_CYCLES(0));
target_mem32_write32(target, RP_SSI_ENABLE, RP_SSI_ENABLE_SSI);
}
static void rp_spi_restore(target_s *const target)
{
const rp_priv_s *const priv = (rp_priv_s *)target->target_storage;
/* Put things back to how they were */
target_mem32_write32(target, RP_SSI_ENABLE, 0);
target_mem32_write32(target, RP_SSI_CTRL1, priv->ctrl1);
target_mem32_write32(target, RP_SSI_CTRL0, priv->ctrl0);
target_mem32_write32(target, RP_SSI_XIP_SPI_CTRL0, priv->xpi_ctrl0);
target_mem32_write32(target, RP_SSI_ENABLE, priv->ssi_enabled);
}
static bool rp_flash_prepare(target_s *const target)
{
DEBUG_TARGET("%s\n", __func__);
/* Suspend the cache, come out of XIP */
rp_flash_connect_internal(target);
rp_flash_exit_xip(target);
/* Configure the SPI controller for our use */
rp_spi_config(target);
/* Preload the SPI Flash write stub */
return target_mem32_write(target, RP_SRAM_BASE, rp_flash_write_stub, sizeof(rp_flash_write_stub)) == 0;
}
static bool rp_flash_resume(target_s *const target)
{
DEBUG_TARGET("%s\n", __func__);
/* Put the SPI controller back how it was when we entered Flash mode */
rp_spi_restore(target);
/* Flush the cache and resume XIP */
rp_flash_flush_cache(target);
rp_flash_enter_xip(target);
target_mem32_write32(target, CORTEXM_AIRCR, CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ);
return true;
}
static bool rp_flash_write(
target_flash_s *const flash, const target_addr_t dest, const void *const src, const size_t length)
{
target_s *const target = flash->t;
const spi_flash_s *const spi_flash = (spi_flash_s *)flash;
/* Load the next block of data and run the stub */
if (target_mem32_write(target, RP_STUB_BUFFER_BASE, src, length))
return false;
return cortexm_run_stub(
target, RP_SRAM_BASE, dest - flash->start, RP_STUB_BUFFER_BASE, length, spi_flash->page_size);
}
static void rp_spi_chip_select(target_s *const target, const uint32_t state)
{
const uint32_t value = target_mem32_read32(target, RP_GPIO_QSPI_CS_CTRL);
target_mem32_write32(target, RP_GPIO_QSPI_CS_CTRL, (value & ~RP_GPIO_QSPI_CS_DRIVE_MASK) | state);
}
static uint8_t rp_spi_xfer_data(target_s *const target, const uint8_t data)
{
target_mem32_write32(target, RP_SSI_DR0, data);
return target_mem32_read32(target, RP_SSI_DR0) & 0xffU;
}
static void rp_spi_setup_xfer(target_s *const target, const uint16_t command, const target_addr32_t address)
{
/* Select the Flash */
rp_spi_chip_select(target, RP_GPIO_QSPI_CS_DRIVE_LOW);
/* Set up the instruction */
const uint8_t opcode = command & SPI_FLASH_OPCODE_MASK;
rp_spi_xfer_data(target, opcode);
if ((command & SPI_FLASH_OPCODE_MODE_MASK) == SPI_FLASH_OPCODE_3B_ADDR) {
/* For each byte sent here, we have to manually clean up from the controller with a read */
rp_spi_xfer_data(target, (address >> 16U) & 0xffU);
rp_spi_xfer_data(target, (address >> 8U) & 0xffU);
rp_spi_xfer_data(target, address & 0xffU);
}
const size_t inter_length = (command & SPI_FLASH_DUMMY_MASK) >> SPI_FLASH_DUMMY_SHIFT;
for (size_t i = 0; i < inter_length; ++i)
/* For each byte sent here, we have to manually clean up from the controller with a read */
rp_spi_xfer_data(target, 0);
}
static void rp_spi_read(target_s *const target, const uint16_t command, const target_addr32_t address,
void *const buffer, const size_t length)
{
/* Setup the transaction */
rp_spi_setup_xfer(target, command, address);
/* Now read back the data that elicited */
uint8_t *const data = (uint8_t *)buffer;
for (size_t i = 0; i < length; ++i)
/* Do a write to read */
data[i] = rp_spi_xfer_data(target, 0);
/* Deselect the Flash */
rp_spi_chip_select(target, RP_GPIO_QSPI_CS_DRIVE_HIGH);
}
static void rp_spi_run_command(target_s *const target, const uint16_t command, const target_addr32_t address)
{
/* Setup the transaction */
rp_spi_setup_xfer(target, command, address);
/* Deselect the Flash to execute the transaction */
rp_spi_chip_select(target, RP_GPIO_QSPI_CS_DRIVE_HIGH);
}
/* Checks if the QSPI and XIP controllers are in their POR state */
static bool rp_flash_in_por_state(target_s *const target)
{
const uint32_t clk_enables0 = target_mem32_read32(target, RP_CLOCKS_WAKE_EN0);
const uint32_t clk_enables1 = target_mem32_read32(target, RP_CLOCKS_WAKE_EN1);
if ((clk_enables0 & RP_CLOCKS_WAKE_EN0_MASK) != RP_CLOCKS_WAKE_EN0_MASK ||
(clk_enables1 & RP_CLOCKS_WAKE_EN1_MASK) != RP_CLOCKS_WAKE_EN1_MASK) {
/* If the right clocks aren't enabled, enable all of them just like the boot ROM does. */
target_mem32_write32(target, RP_CLOCKS_WAKE_EN0, 0xffffffffU);
target_mem32_write32(target, RP_CLOCKS_WAKE_EN1, 0xffffffffU);
return true;
}
const uint32_t pad_sclk_state = target_mem32_read32(target, RP_PADS_QSPI_GPIO_SCLK);
/* If input is enabled on the SPI clock pin, we're not configured. */
if (pad_sclk_state & RP_PADS_QSPI_GPIO_SCLK_IE)
return true;
const uint32_t xip_state = target_mem32_read32(target, RP_XIP_STAT);
const uint32_t qspi_sclk_state = target_mem32_read32(target, RP_GPIO_QSPI_SCLK_CTRL);
const uint32_t ssi_state = target_mem32_read32(target, RP_SSI_ENABLE);
/* Check the XIP, QSPI and SSI controllers for their POR states, indicating we need to configure them */
return xip_state == RP_XIP_STAT_POR && qspi_sclk_state == RP_GPIO_QSPI_SCLK_POR && ssi_state == 0U;
}
// Connect the XIP controller to the flash pads
static void rp_flash_connect_internal(target_s *const target)
{
// Use hard reset to force IO and pad controls to known state (don't touch
// IO_BANK0 as that does not affect XIP signals)
const uint32_t io_pads_bits = RP_RESETS_RESET_IO_QSPI_BITS | RP_RESETS_RESET_PADS_QSPI_BITS;
target_mem32_write32(
target, RP_RESETS_RESET | RP_REG_ACCESS_WRITE_ATOMIC_BITSET, io_pads_bits); // Assert the resets
target_mem32_write32(
target, RP_RESETS_RESET | RP_REG_ACCESS_WRITE_ATOMIC_BITCLR, io_pads_bits); // Then deassert them
uint32_t reset_done = 0;
while ((reset_done & io_pads_bits) != io_pads_bits) // Wait until the reset done signals for both come good
reset_done = target_mem32_read32(target, RP_RESETS_RESET_DONE);
// Then mux XIP block onto internal QSPI flash pads
target_mem32_write32(target, RP_GPIO_QSPI_SCLK_CTRL, 0);
target_mem32_write32(target, RP_GPIO_QSPI_CS_CTRL, 0);
target_mem32_write32(target, RP_GPIO_QSPI_SD0_CTRL, 0);
target_mem32_write32(target, RP_GPIO_QSPI_SD1_CTRL, 0);
target_mem32_write32(target, RP_GPIO_QSPI_SD2_CTRL, 0);
target_mem32_write32(target, RP_GPIO_QSPI_SD3_CTRL, 0);
}
// Set up the SSI controller for standard SPI mode,i.e. for every byte sent we get one back
// This is only called by flash_exit_xip(), not by any of the other functions.
// This makes it possible for the debugger or user code to edit SPI settings
// e.g. baud rate, CPOL/CPHA.
static void rp_flash_init_spi(target_s *const target)
{
// Disable SSI for further config
target_mem32_write32(target, RP_SSI_ENABLE, 0);
// Clear sticky errors (clear-on-read)
target_mem32_read32(target, RP_SSI_SR);
target_mem32_read32(target, RP_SSI_ICR);
// Hopefully-conservative baud rate for boot and programming
target_mem32_write32(target, RP_SSI_BAUD, 6);
target_mem32_write32(target, RP_SSI_CTRL0,
RP_SSI_CTRL0_FRF_SERIAL | // Standard 1-bit SPI serial frames
RP_SSI_CTRL0_DATA_BITS(8) | // 8 clocks per data frame
RP_SSI_CTRL0_TMOD_BIDI // TX and RX FIFOs are both used for every byte
);
// Slave selected when transfers in progress
target_mem32_write32(target, RP_SSI_SER, 1);
// Re-enable
target_mem32_write32(target, RP_SSI_ENABLE, 1);
}
// Also allow any unbounded loops to check whether the above abort condition
// was asserted, and terminate early
static bool rp_flash_was_aborted(target_s *const target)
{
return target_mem32_read32(target, RP_GPIO_QSPI_SD1_CTRL) & RP_GPIO_QSPI_SD1_CTRL_INOVER_BITS;
}
// Put bytes from one buffer, and get bytes into another buffer.
// These can be the same buffer.
// If tx is NULL then send zeroes.
// If rx is NULL then all read data will be dropped.
//
// If rx_skip is nonzero, this many bytes will first be consumed from the FIFO,
// before reading a further count bytes into *rx.
// E.g. if you have written a command+address just before calling this function.
static void rp_flash_put_get(
target_s *const target, const uint8_t *const tx, uint8_t *const rx, const size_t count, size_t rx_skip)
{
// Make sure there is never more data in flight than the depth of the RX
// FIFO. Otherwise, when we are interrupted for long periods, hardware
// will overflow the RX FIFO.
static const size_t max_in_flight = 16U - 2U; // account for data internal to SSI
size_t tx_count = 0;
size_t rx_count = 0;
while (tx_count < count || rx_count < count || rx_skip) {
// NB order of reads, for pessimism rather than optimism
const uint32_t tx_level = target_mem32_read32(target, RP_SSI_TXFLR);
const uint32_t rx_level = target_mem32_read32(target, RP_SSI_RXFLR);
bool idle = true; // Expect this to be folded into control flow, not register
if (tx_count < count && tx_level + rx_level < max_in_flight) {
target_mem32_write32(target, RP_SSI_DR0, (uint32_t)(tx ? tx[tx_count] : 0));
++tx_count;
idle = false;
}
if (rx_level) {
const uint8_t data = target_mem32_read32(target, RP_SSI_DR0);
if (rx_skip)
--rx_skip;
else {
if (rx)
rx[rx_count] = data;
++rx_count;
}
idle = false;
}
// APB load costs 4 cycles, so only do it on idle loops (our budget is 48 cyc/byte)
if (idle && rp_flash_was_aborted(target))
break;
}
rp_spi_chip_select(target, RP_GPIO_QSPI_CS_DRIVE_HIGH);
}
// Sequence:
// 1. CSn = 1, IO = 4'h0 (via pulldown to avoid contention), x32 clocks
// 2. CSn = 0, IO = 4'hf (via pullup to avoid contention), x32 clocks
// 3. CSn = 1 (brief deassertion)
// 4. CSn = 0, MOSI = 1'b1 driven, x16 clocks
//
// Part 4 is the sequence suggested in W25X10CL datasheet.
// Parts 1 and 2 are to improve compatibility with Micron parts
static void rp_flash_exit_xip(target_s *const target)
{
uint8_t buf[2];
memset(buf, 0xffU, sizeof(buf));
rp_flash_init_spi(target);
uint32_t padctrl_save = target_mem32_read32(target, RP_PADS_QSPI_GPIO_SD0);
uint32_t padctrl_tmp =
(padctrl_save &
~(RP_PADS_QSPI_GPIO_SD0_OD_BITS | RP_PADS_QSPI_GPIO_SD0_PUE_BITS | RP_PADS_QSPI_GPIO_SD0_PDE_BITS)) |
RP_PADS_QSPI_GPIO_SD0_OD_BITS | RP_PADS_QSPI_GPIO_SD0_PDE_BITS;
// First two 32-clock sequences
// CSn is held high for the first 32 clocks, then asserted low for next 32
rp_spi_chip_select(target, RP_GPIO_QSPI_CS_DRIVE_HIGH);
for (size_t i = 0; i < 2U; ++i) {
// This gives 4 16-bit offset store instructions. Anything else seems to
// produce a large island of constants
target_mem32_write32(target, RP_PADS_QSPI_GPIO_SD0, padctrl_tmp);
target_mem32_write32(target, RP_PADS_QSPI_GPIO_SD1, padctrl_tmp);
target_mem32_write32(target, RP_PADS_QSPI_GPIO_SD2, padctrl_tmp);
target_mem32_write32(target, RP_PADS_QSPI_GPIO_SD3, padctrl_tmp);
// Brief delay (~6000 cyc) for pulls to take effect
platform_delay(10);
rp_flash_put_get(target, NULL, NULL, 4, 0);
padctrl_tmp = (padctrl_tmp & ~RP_PADS_QSPI_GPIO_SD0_PDE_BITS) | RP_PADS_QSPI_GPIO_SD0_PUE_BITS;
rp_spi_chip_select(target, RP_GPIO_QSPI_CS_DRIVE_LOW);
}
// Restore IO/pad controls, and send 0xff, 0xff. Put pullup on IO2/IO3 as
// these may be used as WPn/HOLDn at this point, and we are now starting
// to issue serial commands.
target_mem32_write32(target, RP_PADS_QSPI_GPIO_SD0, padctrl_save);
target_mem32_write32(target, RP_PADS_QSPI_GPIO_SD1, padctrl_save);
padctrl_save = (padctrl_save & ~RP_PADS_QSPI_GPIO_SD0_PDE_BITS) | RP_PADS_QSPI_GPIO_SD0_PUE_BITS;
target_mem32_write32(target, RP_PADS_QSPI_GPIO_SD2, padctrl_save);
target_mem32_write32(target, RP_PADS_QSPI_GPIO_SD3, padctrl_save);
rp_spi_chip_select(target, RP_GPIO_QSPI_CS_DRIVE_LOW);
rp_flash_put_get(target, buf, NULL, 2, 0);
target_mem32_write32(target, RP_GPIO_QSPI_CS_CTRL, 0);
}
// This is a hook for steps to be taken in between programming the flash and
// doing cached XIP reads from the flash. Called by the bootrom before
// entering flash second stage, and called by the debugger after flash
// programming.
static void rp_flash_flush_cache(target_s *const target)
{
target_mem32_write32(target, RP_XIP_FLUSH, 1);
// Read blocks until flush completion
target_mem32_read32(target, RP_XIP_FLUSH);
// Enable the cache
target_mem32_write32(target, RP_XIP_CTRL | RP_REG_ACCESS_WRITE_ATOMIC_BITSET, RP_XIP_CTRL_ENABLE);
rp_spi_chip_select(target, RP_GPIO_QSPI_CS_DRIVE_NORMAL);
}
// Put the SSI into a mode where XIP accesses translate to standard
// serial 03h read commands. The flash remains in its default serial command
// state, so will still respond to other commands.
static void rp_flash_enter_xip(target_s *const target)
{
target_mem32_write32(target, RP_SSI_ENABLE, 0);
target_mem32_write32(target, RP_SSI_CTRL0,
RP_SSI_CTRL0_FRF_SERIAL | // Standard 1-bit SPI serial frames
RP_SSI_CTRL0_DATA_BITS(32U) | // 32 clocks per data frame
RP_SSI_CTRL0_TMOD_EEPROM // Send instr + addr, receive data
);
target_mem32_write32(target, RP_SSI_XIP_SPI_CTRL0,
RP_SSI_XIP_SPI_CTRL0_XIP_CMD(0x03U) | // Standard 03h read
RP_SSI_XIP_SPI_CTRL0_INSTR_LENGTH_8b | // 8-bit instruction prefix
RP_SSI_XIP_SPI_CTRL0_ADDRESS_LENGTH(0x03U) | // 24-bit addressing for 03h commands
RP_SSI_XIP_SPI_CTRL0_TRANS_1C1A // Command and address both in serial format
);
target_mem32_write32(target, RP_SSI_ENABLE, RP_SSI_ENABLE_SSI);
}
static uint32_t rp_get_flash_length(target_s *const target)
{
// Read the JEDEC ID and try to decode it
spi_flash_id_s flash_id;
rp_spi_read(target, SPI_FLASH_CMD_READ_JEDEC_ID, 0, &flash_id, sizeof(flash_id));
DEBUG_INFO("Flash device ID: %02x %02x %02x\n", flash_id.manufacturer, flash_id.type, flash_id.capacity);
if (flash_id.capacity >= 8U && flash_id.capacity <= 34U)
return 1U << flash_id.capacity;
// Guess maximum flash size
return MAX_FLASH;
}
static bool rp_cmd_erase_sector(target_s *target, int argc, const char **argv)
{
uint32_t start = target->flash->start;
uint32_t length;
if (argc == 3) {
start = strtoul(argv[1], NULL, 0);
length = strtoul(argv[2], NULL, 0);
} else if (argc == 2)
length = strtoul(argv[1], NULL, 0);
else
return false;
target_flash_s *const flash = target->flash;
bool result = true; /* catch false returns with &= */
result &= rp_flash_prepare(target);
result &= flash->erase(flash, start, length);
result &= rp_flash_resume(target);
return result;
}
static bool rp_cmd_reset_usb_boot(target_s *t, int argc, const char **argv)
{
uint32_t regs[20U] = {0};
rp_priv_s *ps = (rp_priv_s *)t->target_storage;
/* Set up the arguments for the function call */
if (argc > 1)
regs[0] = strtoul(argv[1], NULL, 0);
if (argc > 2)
regs[1] = strtoul(argv[2], NULL, 0);
/* The USB boot function does not return and takes its arguments in r0 and r1 */
regs[CORTEX_REG_PC] = ps->rom_reset_usb_boot;
/* So load the link register with a dummy return address like we just booted the chip */
regs[CORTEX_REG_LR] = UINT32_MAX;
/* Configure the stack to the end of SRAM and configure the status register for Thumb execution */
regs[CORTEX_REG_MSP] = RP_SRAM_BASE + RP_SRAM_SIZE;
regs[CORTEX_REG_XPSR] = CORTEXM_XPSR_THUMB;
/* Now reconfigure the core with the new execution environment */
target_regs_write(t, regs);
/* And resume the core */
target_halt_resume(t, false);
return true;
}
static bool rp2040_rescue_do_reset(target_s *target)
{
adiv5_access_port_s *ap = (adiv5_access_port_s *)target->priv;
const uint32_t ctrl = adiv5_dp_read(ap->dp, ADIV5_DP_CTRLSTAT);
adiv5_dp_write(ap->dp, ADIV5_DP_CTRLSTAT, ctrl | ADIV5_DP_CTRLSTAT_CDBGPWRUPREQ);
platform_timeout_s timeout;
platform_timeout_set(&timeout, 100);
while (true) {
const uint32_t status = adiv5_dp_read(ap->dp, ADIV5_DP_CTRLSTAT);
if (!(status & ADIV5_DP_CTRLSTAT_CDBGRSTACK)) {
DEBUG_INFO("RP2040 Rescue success\n");
break;
}
if (platform_timeout_is_expired(&timeout)) {
DEBUG_INFO("RP2040 Rescue failed\n");
break;
}
}
return false;
}
/*
* The RP2040 rescue DP provides no AP, so we need special handling
*
* Attach to this DP will do the reset, but will fail to attach!
*/
bool rp2040_rescue_probe(adiv5_access_port_s *ap)
{
target_s *target = target_new();
if (!target)
return false;
adiv5_ap_ref(ap);
target->attach = rp2040_rescue_do_reset;
target->priv = ap;
target->priv_free = (void (*)(void *))adiv5_ap_unref;
target->driver = "RP2040 Rescue (Attach to reset)";
return true;
}