]> cvs.zerfleddert.de Git - proxmark3-svn/blob - bootrom/bootrom.c
Initial commit for the firmware. Used the 20090306_ela version as baseline.
[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 void BootROM(void)
111 {
112 //------------
113 // First set up all the I/O pins; GPIOs configured directly, other ones
114 // just need to be assigned to the appropriate peripheral.
115
116 // Kill all the pullups, especially the one on USB D+; leave them for
117 // the unused pins, though.
118 PIO_NO_PULL_UP_ENABLE = (1 << GPIO_USB_PU) |
119 (1 << GPIO_LED_A) |
120 (1 << GPIO_LED_B) |
121 (1 << GPIO_LED_C) |
122 (1 << GPIO_LED_D) |
123 (1 << GPIO_FPGA_DIN) |
124 (1 << GPIO_FPGA_DOUT) |
125 (1 << GPIO_FPGA_CCLK) |
126 (1 << GPIO_FPGA_NINIT) |
127 (1 << GPIO_FPGA_NPROGRAM) |
128 (1 << GPIO_FPGA_DONE) |
129 (1 << GPIO_MUXSEL_HIPKD) |
130 (1 << GPIO_MUXSEL_HIRAW) |
131 (1 << GPIO_MUXSEL_LOPKD) |
132 (1 << GPIO_MUXSEL_LORAW) |
133 (1 << GPIO_RELAY) |
134 (1 << GPIO_NVDD_ON);
135 // (and add GPIO_FPGA_ON)
136 // These pins are outputs
137 PIO_OUTPUT_ENABLE = (1 << GPIO_LED_A) |
138 (1 << GPIO_LED_B) |
139 (1 << GPIO_LED_C) |
140 (1 << GPIO_LED_D) |
141 (1 << GPIO_RELAY) |
142 (1 << GPIO_NVDD_ON);
143 // PIO controls the following pins
144 PIO_ENABLE = (1 << GPIO_USB_PU) |
145 (1 << GPIO_LED_A) |
146 (1 << GPIO_LED_B) |
147 (1 << GPIO_LED_C) |
148 (1 << GPIO_LED_D);
149
150 USB_D_PLUS_PULLUP_OFF();
151 LED_D_OFF();
152 LED_C_ON();
153 LED_B_OFF();
154 LED_A_OFF();
155
156 // if 512K FLASH part - TODO make some defines :)
157 if ((DBGU_CIDR | 0xf00) == 0xa00) {
158 MC_FLASH_MODE0 = MC_FLASH_MODE_FLASH_WAIT_STATES(1) |
159 MC_FLASH_MODE_MASTER_CLK_IN_MHZ(0x48);
160 MC_FLASH_MODE1 = MC_FLASH_MODE_FLASH_WAIT_STATES(1) |
161 MC_FLASH_MODE_MASTER_CLK_IN_MHZ(0x48);
162 } else {
163 MC_FLASH_MODE0 = MC_FLASH_MODE_FLASH_WAIT_STATES(0) |
164 MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48);
165 }
166
167 // Initialize all system clocks
168 ConfigClocks();
169
170 LED_A_ON();
171
172 if(BUTTON_PRESS()) {
173 UsbStart();
174 }
175
176 for(;;) {
177 WDT_HIT();
178
179 UsbPoll(TRUE);
180
181 if(!BUTTON_PRESS()) {
182 USB_D_PLUS_PULLUP_OFF();
183 LED_B_ON();
184
185 // jump to RAM address 0x10000 (LSBit set for thumb mode)
186 asm("ldr r3, = 0x10001\n");
187 asm("bx r3\n");
188 }
189 }
190 }
Impressum, Datenschutz