]> cvs.zerfleddert.de Git - proxmark3-svn/blob - bootrom/bootrom.c
New flash tool, needs to be ported to Windows.
[proxmark3-svn] / bootrom / bootrom.c
1 #include <proxmark3.h>
2
3 static void ConfigClocks(void)
4 {
5 // we are using a 16 MHz crystal as the basis for everything
6 // slow clock runs at 32Khz typical regardless of crystal
7
8 // enable system clock and USB clock
9 PMC_SYS_CLK_ENABLE = PMC_SYS_CLK_PROCESSOR_CLK | PMC_SYS_CLK_UDP_CLK;
10
11 // enable the clock to the following peripherals
12 PMC_PERIPHERAL_CLK_ENABLE =
13 (1<<PERIPH_PIOA) |
14 (1<<PERIPH_ADC) |
15 (1<<PERIPH_SPI) |
16 (1<<PERIPH_SSC) |
17 (1<<PERIPH_PWMC) |
18 (1<<PERIPH_UDP);
19
20 // worst case scenario, with 16Mhz xtal startup delay is 14.5ms
21 // with a slow clock running at it worst case (max) frequency of 42khz
22 // max startup delay = (14.5ms*42k)/8 = 76 = 0x4C round up to 0x50
23
24 // enable main oscillator and set startup delay
25 PMC_MAIN_OSCILLATOR = PMC_MAIN_OSCILLATOR_ENABLE |
26 PMC_MAIN_OSCILLATOR_STARTUP_DELAY(0x50);
27
28 // wait for main oscillator to stabilize
29 while ( !(PMC_INTERRUPT_STATUS & PMC_MAIN_OSCILLATOR_STABILIZED) )
30 ;
31
32 // minimum PLL clock frequency is 80 MHz in range 00 (96 here so okay)
33 // frequency is crystal * multiplier / divisor = 16Mhz * 12 / 2 = 96Mhz
34 PMC_PLL = PMC_PLL_DIVISOR(2) | PMC_PLL_COUNT_BEFORE_LOCK(0x50) |
35 PMC_PLL_FREQUENCY_RANGE(0) | PMC_PLL_MULTIPLIER(12) |
36 PMC_PLL_USB_DIVISOR(1);
37
38 // wait for PLL to lock
39 while ( !(PMC_INTERRUPT_STATUS & PMC_MAIN_OSCILLATOR_PLL_LOCK) )
40 ;
41
42 // we want a master clock (MCK) to be PLL clock / 2 = 96Mhz / 2 = 48Mhz
43 // as per datasheet, this register must be programmed in two operations
44 // when changing to PLL, program the prescaler first then the source
45 PMC_MASTER_CLK = PMC_CLK_PRESCALE_DIV_2;
46
47 // wait for main clock ready signal
48 while ( !(PMC_INTERRUPT_STATUS & PMC_MAIN_OSCILLATOR_MCK_READY) )
49 ;
50
51 // set the source to PLL
52 PMC_MASTER_CLK = PMC_CLK_SELECTION_PLL_CLOCK | PMC_CLK_PRESCALE_DIV_2;
53
54 // wait for main clock ready signal
55 while ( !(PMC_INTERRUPT_STATUS & PMC_MAIN_OSCILLATOR_MCK_READY) )
56 ;
57 }
58
59 static void Fatal(void)
60 {
61 for(;;);
62 }
63
64 void UsbPacketReceived(BYTE *packet, int len)
65 {
66 int i;
67 UsbCommand *c = (UsbCommand *)packet;
68 volatile DWORD *p;
69
70 if(len != sizeof(*c)) {
71 Fatal();
72 }
73
74 switch(c->cmd) {
75 case CMD_DEVICE_INFO:
76 break;
77
78 case CMD_SETUP_WRITE:
79 p = (volatile DWORD *)0;
80 for(i = 0; i < 12; i++) {
81 p[i+c->ext1] = c->d.asDwords[i];
82 }
83 break;
84
85 case CMD_FINISH_WRITE:
86 p = (volatile DWORD *)0;
87 for(i = 0; i < 4; i++) {
88 p[i+60] = c->d.asDwords[i];
89 }
90
91 MC_FLASH_COMMAND = MC_FLASH_COMMAND_KEY |
92 MC_FLASH_COMMAND_PAGEN(c->ext1/FLASH_PAGE_SIZE_BYTES) |
93 FCMD_WRITE_PAGE;
94 while(!(MC_FLASH_STATUS & MC_FLASH_STATUS_READY))
95 ;
96 break;
97
98 case CMD_HARDWARE_RESET:
99 break;
100
101 default:
102 Fatal();
103 break;
104 }
105
106 c->cmd = CMD_ACK;
107 UsbSendPacket(packet, len);
108 }
109
110 extern char _osimage_entry;
111 void BootROM(void)
112 {
113 //------------
114 // First set up all the I/O pins; GPIOs configured directly, other ones
115 // just need to be assigned to the appropriate peripheral.
116
117 // Kill all the pullups, especially the one on USB D+; leave them for
118 // the unused pins, though.
119 PIO_NO_PULL_UP_ENABLE = (1 << GPIO_USB_PU) |
120 (1 << GPIO_LED_A) |
121 (1 << GPIO_LED_B) |
122 (1 << GPIO_LED_C) |
123 (1 << GPIO_LED_D) |
124 (1 << GPIO_FPGA_DIN) |
125 (1 << GPIO_FPGA_DOUT) |
126 (1 << GPIO_FPGA_CCLK) |
127 (1 << GPIO_FPGA_NINIT) |
128 (1 << GPIO_FPGA_NPROGRAM) |
129 (1 << GPIO_FPGA_DONE) |
130 (1 << GPIO_MUXSEL_HIPKD) |
131 (1 << GPIO_MUXSEL_HIRAW) |
132 (1 << GPIO_MUXSEL_LOPKD) |
133 (1 << GPIO_MUXSEL_LORAW) |
134 (1 << GPIO_RELAY) |
135 (1 << GPIO_NVDD_ON);
136 // (and add GPIO_FPGA_ON)
137 // These pins are outputs
138 PIO_OUTPUT_ENABLE = (1 << GPIO_LED_A) |
139 (1 << GPIO_LED_B) |
140 (1 << GPIO_LED_C) |
141 (1 << GPIO_LED_D) |
142 (1 << GPIO_RELAY) |
143 (1 << GPIO_NVDD_ON);
144 // PIO controls the following pins
145 PIO_ENABLE = (1 << GPIO_USB_PU) |
146 (1 << GPIO_LED_A) |
147 (1 << GPIO_LED_B) |
148 (1 << GPIO_LED_C) |
149 (1 << GPIO_LED_D);
150
151 USB_D_PLUS_PULLUP_OFF();
152 LED_D_OFF();
153 LED_C_ON();
154 LED_B_OFF();
155 LED_A_OFF();
156
157 // if 512K FLASH part - TODO make some defines :)
158 if ((DBGU_CIDR | 0xf00) == 0xa00) {
159 MC_FLASH_MODE0 = MC_FLASH_MODE_FLASH_WAIT_STATES(1) |
160 MC_FLASH_MODE_MASTER_CLK_IN_MHZ(0x48);
161 MC_FLASH_MODE1 = MC_FLASH_MODE_FLASH_WAIT_STATES(1) |
162 MC_FLASH_MODE_MASTER_CLK_IN_MHZ(0x48);
163 } else {
164 MC_FLASH_MODE0 = MC_FLASH_MODE_FLASH_WAIT_STATES(0) |
165 MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48);
166 }
167
168 // Initialize all system clocks
169 ConfigClocks();
170
171 LED_A_ON();
172
173 if(BUTTON_PRESS()) {
174 UsbStart();
175 }
176
177 for(;;) {
178 WDT_HIT();
179
180 UsbPoll(TRUE);
181
182 if(!BUTTON_PRESS()) {
183 USB_D_PLUS_PULLUP_OFF();
184 LED_B_ON();
185
186 // jump to Flash address of the osimage entry point (LSBit set for thumb mode)
187 asm("bx %0\n" : : "r" ( ((int)&_osimage_entry) | 0x1 ) );
188 }
189 }
190 }
Impressum, Datenschutz