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