38
|
1 /**
|
|
2 ******************************************************************************
|
|
3 * @file externCPU2bootloader.c Template
|
|
4 * @author heinrichs weikamp gmbh
|
|
5 * @version V0.0.1
|
|
6 * @date 23-Oct-2014
|
|
7 * @version V0.0.1
|
|
8 * @since 23-Oct-2014
|
|
9 * @brief Main Template to communicate with the second CPU in bootloader mode
|
|
10 * bootloader ROM build by ST and defined in AN4286
|
|
11 *
|
|
12 @verbatim
|
|
13 ==============================================================================
|
|
14 ##### How to use #####
|
|
15 ==============================================================================
|
|
16 @endverbatim
|
|
17 ******************************************************************************
|
|
18 * @attention
|
|
19 *
|
|
20 * <h2><center>© COPYRIGHT(c) 2016 heinrichs weikamp</center></h2>
|
|
21 *
|
|
22 ******************************************************************************
|
|
23 */
|
|
24
|
|
25 /* Includes ------------------------------------------------------------------*/
|
|
26 #include "stm32f4xx_hal.h"
|
|
27 #include "stdio.h"
|
|
28 #include "ostc.h"
|
|
29 #include "settings.h"
|
|
30 #include "externCPU2bootloader.h"
|
|
31 #include "externLogbookFlash.h"
|
|
32 #include "tComm.h"
|
|
33
|
|
34
|
|
35 /* Exported variables --------------------------------------------------------*/
|
|
36
|
|
37 /* Private types -------------------------------------------------------------*/
|
|
38 #define BOOTLOADSPITIMEOUT 5000
|
|
39
|
|
40 /* Private variables ---------------------------------------------------------*/
|
|
41
|
|
42 /* Private function prototypes -----------------------------------------------*/
|
|
43
|
|
44 uint8_t boot_sync_frame(void);
|
|
45 uint8_t boot_ack(void);
|
|
46 uint8_t boot_get(uint8_t *RxBuffer);
|
|
47 uint8_t boot_get_id(uint8_t *RxBuffer);
|
|
48 uint8_t boot_get_version(uint8_t *RxBuffer);
|
|
49 //uint8_t boot_go(uint32_t address);
|
|
50 uint8_t boot_write_memory(uint32_t address, uint8_t length_minus_1, uint8_t *data);
|
|
51 //uint8_t boot_erase_memory(uint16_t data_frame, uint16_t *page_numbers);
|
|
52 uint8_t boot_erase_memory(void);
|
|
53 uint8_t boot_write_protect(uint8_t number_of_sectors_minus_one, uint8_t *sector_codes);
|
|
54 /*
|
|
55 uint8_t boot_write_unprotect(void);
|
|
56 uint8_t boot_readout_protect(void);
|
|
57 uint8_t boot_readout_unprotect(void);
|
|
58 */
|
|
59 void Bootoader_send_command(uint8_t command);
|
|
60 void Bootloader_spi_single(uint8_t TxByte);
|
|
61 void Bootloader_spi(uint16_t lengthData, uint8_t *aTxBuffer, uint8_t *aRxBuffer);
|
|
62 void Bootloader_Error_Handler(void);
|
|
63
|
|
64 /* Exported functions --------------------------------------------------------*/
|
|
65
|
|
66 uint8_t extCPU2bootloader_start(uint8_t *version, uint16_t *chipID)
|
|
67 {
|
|
68 // uint8_t aTxBuffer[256] = { 0 };
|
|
69 uint8_t aRxBuffer[256] = { 0 };
|
|
70
|
|
71 HAL_GPIO_WritePin(SMALLCPU_CSB_GPIO_PORT,SMALLCPU_CSB_PIN,GPIO_PIN_RESET);
|
|
72
|
|
73 boot_sync_frame();
|
|
74 boot_get_version(aRxBuffer);
|
|
75 *version = aRxBuffer[1];
|
|
76 HAL_Delay(10);
|
|
77 boot_get_id(aRxBuffer);
|
|
78 *chipID = ((uint16_t)aRxBuffer[2]) << 8;
|
|
79 *chipID += (uint16_t)aRxBuffer[3];
|
|
80 HAL_Delay(10);
|
|
81 if((*chipID == 0x431) && (*version > 10) && (*version < 32))
|
|
82 return 1;
|
|
83 else
|
|
84 return 0;
|
|
85 }
|
|
86
|
|
87
|
|
88 uint8_t extCPU2bootloader_internal(uint8_t* buffer, uint16_t length, char* display_text)
|
|
89 {
|
|
90 uint8_t version = 0;
|
|
91 uint16_t chipID = 0;
|
|
92 // uint8_t ret;
|
|
93 if(!extCPU2bootloader_start(&version,&chipID))
|
|
94 return 0;
|
|
95 if(!boot_erase_memory())
|
|
96 return 0;
|
|
97 HAL_Delay(100);
|
|
98 uint16_t i=0;
|
|
99 uint16_t lengthsave = length;
|
|
100 uint8_t percent = 0;
|
|
101
|
|
102 while(length)
|
|
103 {
|
|
104 percent = (100 * (i * 256)) /lengthsave;
|
|
105 tComm_verlauf(percent);
|
|
106
|
|
107 if(length > 256)
|
|
108 {
|
|
109 if( !boot_write_memory(0x08000000 + (i * 256), 255, &buffer[i * 256]) )
|
|
110 return 0;;
|
|
111 length -= 256;
|
|
112
|
|
113 }
|
|
114 else
|
|
115 {
|
|
116 if(!boot_write_memory(0x08000000 + (i * 256), length - 1, &buffer[i * 256]))
|
|
117 return 0;
|
|
118 length = 0;
|
|
119 }
|
|
120 i++;
|
|
121 }
|
|
122 return 2;
|
|
123 }
|
|
124
|
|
125
|
|
126 uint8_t extCPU2bootloader(uint8_t* buffer, uint16_t length, char* display_text)
|
|
127 {
|
|
128 uint8_t result = 0;
|
|
129
|
|
130 MX_SmallCPU_Reset_To_Boot();
|
|
131 result = extCPU2bootloader_internal(buffer,length,display_text);
|
|
132 MX_SmallCPU_Reset_To_Standard();
|
|
133 return result;
|
|
134 }
|
|
135
|
|
136 /* Private functions --------------------------------------------------------*/
|
|
137
|
|
138 uint8_t boot_sync_frame(void)
|
|
139 {
|
|
140 Bootloader_spi_single(0x5a);
|
|
141 return boot_ack();
|
|
142 }
|
|
143
|
|
144
|
|
145 uint8_t boot_get(uint8_t *RxBuffer)
|
|
146 {
|
|
147 Bootloader_spi_single(0x5a);
|
|
148 Bootoader_send_command(0x00);
|
|
149 if(!boot_ack())
|
|
150 return 0;
|
|
151 Bootloader_spi(14, NULL, RxBuffer);
|
|
152 return boot_ack();
|
|
153 }
|
|
154
|
|
155
|
|
156 uint8_t boot_get_version(uint8_t *RxBuffer)
|
|
157 {
|
|
158 Bootloader_spi_single(0x5a);
|
|
159 Bootoader_send_command(0x01);
|
|
160 if(!boot_ack())
|
|
161 return 0;
|
|
162 Bootloader_spi(3, NULL, RxBuffer);
|
|
163 return boot_ack();
|
|
164 }
|
|
165
|
|
166
|
|
167 uint8_t boot_get_id(uint8_t *RxBuffer)
|
|
168 {
|
|
169 Bootloader_spi_single(0x5a);
|
|
170 Bootoader_send_command(0x02);
|
|
171 if(!boot_ack())
|
|
172 return 0;
|
|
173 Bootloader_spi(5, NULL, RxBuffer);
|
|
174 return boot_ack();
|
|
175 }
|
|
176
|
|
177 /*
|
|
178 uint8_t boot_go(uint32_t address)
|
|
179 {
|
|
180
|
|
181 }
|
|
182 */
|
|
183
|
|
184
|
|
185 uint8_t boot_write_memory(uint32_t address, uint8_t length_minus_1, uint8_t *data)
|
|
186 {
|
|
187 uint8_t addressNew[4];
|
|
188 uint8_t checksum = 0;
|
|
189 uint16_t length;
|
|
190
|
|
191 Bootloader_spi_single(0x5a);
|
|
192 Bootoader_send_command(0x31);
|
|
193 if(!boot_ack())
|
|
194 return 1;
|
|
195 HAL_Delay(5);
|
|
196 addressNew[0] = (uint8_t)((address >> 24) & 0xFF);
|
|
197 addressNew[1] = (uint8_t)((address >> 16) & 0xFF);
|
|
198 addressNew[2] = (uint8_t)((address >> 8) & 0xFF);
|
|
199 addressNew[3] = (uint8_t)((address >> 0) & 0xFF);
|
|
200 Bootloader_spi(4, addressNew, NULL);
|
|
201 checksum = 0;
|
|
202 checksum ^= addressNew[0];
|
|
203 checksum ^= addressNew[1];
|
|
204 checksum ^= addressNew[2];
|
|
205 checksum ^= addressNew[3];
|
|
206 Bootloader_spi_single(checksum);
|
|
207 if(!boot_ack())
|
|
208 return 0;
|
|
209 HAL_Delay(1);
|
|
210 Bootloader_spi_single(length_minus_1);
|
|
211 length = ((uint16_t)length_minus_1) + 1;
|
|
212 Bootloader_spi(length, data, NULL);
|
|
213 HAL_Delay(26);
|
|
214 checksum = 0;
|
|
215 checksum ^= length_minus_1;
|
|
216 for(int i=0;i<length;i++)
|
|
217 checksum ^= data[i];
|
|
218 Bootloader_spi_single(checksum);
|
|
219
|
|
220 if(!boot_ack())
|
|
221 return 0;
|
|
222 HAL_Delay(1);
|
|
223 return 1;
|
|
224 }
|
|
225
|
|
226 //uint8_t boot_erase_memory(uint16_t data_frame, uint16_t *page_numbers)
|
|
227 uint8_t boot_erase_memory(void)
|
|
228 {
|
|
229 uint8_t special_erase_with_checksum[3] = {0xFF, 0xFF, 0x00};
|
|
230
|
|
231 Bootloader_spi_single(0x5a);
|
|
232 Bootoader_send_command(0x44);
|
|
233 if(!boot_ack())
|
|
234 return 0;
|
|
235 Bootloader_spi(3, special_erase_with_checksum, NULL);
|
|
236 HAL_Delay(11000); /* 5.5 to 11 seconds */
|
|
237 if(!boot_ack())
|
|
238 return 0;
|
|
239 return 1;
|
|
240 }
|
|
241
|
|
242 /* write unprotect does reset the system !! */
|
|
243 uint8_t boot_write_unprotect(void)
|
|
244 {
|
|
245 Bootloader_spi_single(0x5a);
|
|
246 Bootoader_send_command(0x73);
|
|
247 if(!boot_ack())
|
|
248 return 0;
|
|
249 return boot_ack();
|
|
250 }
|
|
251
|
|
252 /*
|
|
253 uint8_t boot_write_protect(uint8_t number_of_sectors_minus_one, uint8_t *sector_codes)
|
|
254 {
|
|
255
|
|
256 }
|
|
257
|
|
258 uint8_t boot_readout_protect(void)
|
|
259 {
|
|
260
|
|
261 }
|
|
262
|
|
263 uint8_t boot_readout_unprotect(void)
|
|
264 {
|
|
265
|
|
266 }
|
|
267 */
|
|
268
|
|
269 uint8_t boot_ack(void)
|
|
270 {
|
|
271 uint8_t answer = 0;
|
|
272
|
|
273 Bootloader_spi_single(0x00);
|
|
274 for(int i=0; i< 1000; i++)
|
|
275 {
|
|
276 Bootloader_spi(1, NULL, &answer);
|
|
277 if((answer == 0x79) || (answer == 0x1F))
|
|
278 {
|
|
279 Bootloader_spi_single(0x79);
|
|
280 break;
|
|
281 }
|
|
282 HAL_Delay(10);
|
|
283 }
|
|
284 if(answer == 0x79)
|
|
285 return 1;
|
|
286 else
|
|
287 return 0;
|
|
288 }
|
|
289
|
|
290 void Bootoader_send_command(uint8_t command)
|
|
291 {
|
|
292 uint8_t send[2];
|
|
293 uint8_t receive[2];
|
|
294
|
|
295 send[0] = command;
|
|
296 send[1] = 0xFF ^ command;
|
|
297 Bootloader_spi(2, send, receive);
|
|
298 }
|
|
299
|
|
300 void Bootloader_spi_single(uint8_t TxByte)
|
|
301 {
|
|
302 Bootloader_spi(1,&TxByte, 0);
|
|
303 }
|
|
304
|
|
305
|
|
306 void Bootloader_spi(uint16_t lengthData, uint8_t *aTxBuffer, uint8_t *aRxBuffer)
|
|
307 {
|
|
308 uint8_t dummy[256] = { 0 };
|
|
309 uint8_t *tx_data;
|
|
310 uint8_t *rx_data;
|
|
311
|
|
312 tx_data = aTxBuffer;
|
|
313 rx_data = aRxBuffer;
|
|
314
|
|
315 if(aTxBuffer == NULL)
|
|
316 tx_data = dummy;
|
|
317 if(aRxBuffer == NULL)
|
|
318 rx_data = dummy;
|
|
319
|
|
320 //HAL_GPIO_WritePin(OSCILLOSCOPE_GPIO_PORT,OSCILLOSCOPE_PIN,GPIO_PIN_RESET); // only for testing with Oscilloscope
|
|
321
|
|
322
|
|
323 HAL_SPI_TransmitReceive(&cpu2DmaSpi, (uint8_t *)tx_data, (uint8_t *)rx_data, (uint16_t)lengthData,1000);
|
|
324 /*
|
|
325 if(HAL_SPI_TransmitReceive_DMA(&cpu2DmaSpi, (uint8_t *)tx_data, (uint8_t *)rx_data, (uint16_t)lengthData) != HAL_OK)
|
|
326 if(HAL_SPI_TransmitReceive_DMA(&cpu2DmaSpi, (uint8_t *)tx_data, (uint8_t *)rx_data, (uint16_t)lengthData) != HAL_OK)
|
|
327 Bootloader_Error_Handler();
|
|
328
|
|
329 while (HAL_SPI_GetState(&cpu2DmaSpi) != HAL_SPI_STATE_READY)// only for testing with Oscilloscope
|
|
330 {
|
|
331 }
|
|
332 HAL_GPIO_WritePin(OSCILLOSCOPE_GPIO_PORT,OSCILLOSCOPE_PIN,GPIO_PIN_SET); // only for testing with Oscilloscope
|
|
333 */
|
|
334 }
|
|
335
|
|
336
|
|
337 void Bootloader_Error_Handler(void)
|
|
338 {
|
|
339 while(1);
|
|
340 }
|
|
341
|
|
342
|
|
343
|