Callisto4Bootloader: src/bootloader.c Source File

Callisto4Bootloader

bootloader.c
Go to the documentation of this file.
1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2017 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 /* FreeRTOS kernel includes. */
10
11 #include "bootloader_types.h"
12 #include "c4_error_codes.h"
13 #include "c4_qspi.h"
14 #include "c4_parser.h"
15 #include "c4_tftp.h"
16
17 #include "FreeRTOS.h"
18 #include "task.h"
19 #include "queue.h"
20 #include "timers.h"
21
22 //#include <stdio.h>
23 //#include <stdlib.h>
24 //#include <stdarg.h>
25 //#include <ctype.h>
26
27 // LWIP includes
28 //#include "lwip/netif.h"
29 //#include "lwip/sys.h"
30 //#include "lwip/arch.h"
31 //#include "lwip/api.h"
32 #include "lwip/tcpip.h"
33 //#include "lwip/ip.h"
34 //#include "lwip/sockets.h"
35 //#include "lwip/igmp.h"
36 //#include "netif/etharp.h"
37 #if LWIP_DHCP
38 #include "lwip/dhcp.h"
39 #endif
40 #include "enet_ethernetif.h"
41
42 // LWIP-Contrib includes
43 #include "httpserver-netconn.h"
44
45 // NXP includes
46 #include "board.h"
47 //#include "peripherals.h"
48 #include "pin_mux.h" // for BOARD_InitPins()
49 #include "clock_config.h"
50 //#include "MIMXRT1062.h"
51
52 /* Freescale includes. */
53 #include "fsl_device_registers.h"
54 //#include "fsl_debug_console.h"
55 #include "fsl_iomuxc.h"
56 #include "fsl_lpi2c.h"
57
58 /* Other driver headers */
59 //#include "at24c01d.h"
60 #include "sja1105.h"
61 #include "remsdaq_uart.h"
62
63 // CoAP includes
64 //#include "coap_io.h" // for CreateCoapTask()
65
66 // sample value includes
67 //#include "sav_init.h"
68
69 // Includes for PTP task
70 //#include "ptpd.h"
71
72 /* PlatformAPI includes */
73 #include "platform-eeprom-header.h"
74 #include "platform-basetypes.h"
75 #include "platform-memory-map.h"
76
77 /* Platform includes */
78 //#include "platform_startup.h"
79 //#include "platform_main_freertos.h"
80 //#include "platform_coap.h"
81 //#include "platform_sampler_lpspi3_ad8688.h"
82 //#include "ip-macros.h"
83
84 // Fake externs used to force linker to include a QSPI header
85 // Once this code is running inside a bootloader framework, remove these!
86 extern char qspiflash_config; // wrong type!
87 extern char image_vector_table; // wrong type!
88 extern char boot_data; // wrong type!
89
90 /*******************************************************************************
91 * Device configuration
92 ******************************************************************************/
93
94 // Set this to 1 to force the platform to write your settings to EEPROM header
95 #define FORCE_WRITE_TO_EEPROM 0
96
97 #define PTP_APP_MASTER_TEST 0
98
99 #define STACK_INIT_USE_TASK 0
100
101 // Your local settings (these get used if the device has no valid EEPROM header)
102
109 #define configSUPPLIER_CODE 'D'
110 #define configDEVICE 12369
112 #define configOPTION 1
114 #define configREVISION 'A'
116 #define configYEAR 20
118 #define configWEEK 9
120 #define configSERIAL 1
122
129 #define configSERIAL_NUM(str) \
130 snprintf(str, PLATFORM_SERIAL_LEN+1, "%c%05d%02d%c%02d%02d%03d", \
131 configSUPPLIER_CODE, \
132 configDEVICE, \
133 configOPTION, \
134 configREVISION, \
135 configYEAR, \
136 configWEEK, \
137 configSERIAL)
138
139 #define configHOSTNAME "Module-57920"
140 #define configMAC_ADDR(X) X(0x00,0x0e,0xbf,0x33,0x00,0x00) // Remsdaq OUI = 00:0e:bf:xx:xx:xx
141 #define configIP_ADDR(X) X(169,254,154,150) // Set this if you need a static IP
142 #define configNET_MASK(X) X(255,255,255,0) // Set this if you need a netmask
143 #define configGW_ADDR(X) X(0,0,0,0) // Set this if you need a gateway
144 #define configCOAP_ADDR(X) X(224,0,1,187) // I'm not sure how this works yet :-(
145 #define configUSE_DHCP 0 // 0 => false, 1 => true
146
147 #define COAP_TASK_STACK_SIZE (30000 / 4) // Size in 32-bit words, hence "/ 4"
148 #define COAP_TASK_PRIO 4
149
150
151 /*******************************************************************************
152 * Definitions
153 ******************************************************************************/
154
155 #define C4_PRINT(...) printf(__VA_ARGS__)
156
158 static const uint32_t VER_MAJ = 0;
160 static const uint32_t VER_MIN = 1;
162 static const char * const VER_DATE = __DATE__;
164 static const char * const VER_TIME = "time"; // __TIME__;
165
167 static const ptrdiff_t IVT_offset = 0x1000L;
168
171 static const uint32_t CURRENT = 0;
172 static const uint32_t RECOVERY = 1;
174
175 static const uint32_t BUF_LEN = 1024;
176
177 /* System clock name. */
178 #define EXAMPLE_CLOCK_NAME kCLOCK_CoreSysClk
179
180 #define MAIN_THREAD_NAME "Main Thread"
181 #define MAIN_THREAD_STACKSIZE_BYTES 8192
182 #define MAIN_THREAD_PRIO DEFAULT_THREAD_PRIO // FIXME
183
184 /*******************************************************************************
185 * Structures
186 ******************************************************************************/
187
189 typedef union {
190 struct {
191 uint32_t revision:4;
192 uint32_t partNo:12;
193 uint32_t architecture:4;
194 uint32_t variant:4;
195 uint32_t implementer:8;
196 } B;
197 uint32_t R;
198 } CPUID_t;
199
200 /*******************************************************************************
201 * Prototypes
202 ******************************************************************************/
203
204 #if STACK_INIT_USE_TASK
205 static void stack_init(void * pvParams);
206 #else
207 void stack_init(stEEPROM_Header_t *stEEPROM_Header);
208 #endif
209
210 void ipaddress_show(stEEPROM_Header_t *stEEPROM_Header);
211 void coap_join_group(stEEPROM_Header_t *stEEPROM_Header);
212 void main_task(void *pvParam);
213
214 void BOARD_InitLPSPI3(void);
215 void BOARD_InitModuleClock(void);
216
217 //static void tasks_debug(void);
218 void RegisterFactoryConfig(void);
219
220 //static bool ConfigHasBeenEdited( const stPLATFORM_ObjectData_t * pstObjectData );
221
227 void eeprom_header_setdefaults(stEEPROM_Header_t * pstHeader);
238 static void C4_jumpToUserApplication(uint32_t app_start, const char *args);
239
251 static void C4_jump(uint32_t user_sp, uint32_t user_startup, const char *argv);
252
265 static exit_code_t C4_checkExecutable(const serialNOR_t *image);
266
273 static void C4_displayVectorTable(const char *identifier, const serialNOR_t *table);
274
275 static void C4_BootFunc(void *pParam);
276
277 // ----------------------------------
278 // Global variables
279 // ----------------------------------
280
281 volatile char qspifake;
282
283 /*******************************************************************************
284 * Variables
285 ******************************************************************************/
286
287 extern uint32_t __Vectors[];
288 extern uint32_t __boot_hdr_start__[];
289 extern uint32_t __boot_hdr_end__[];
290 extern uint32_t *__vectors_start__;
291 extern uint32_t *__section_table_start;
292 extern unsigned int __data_section_table;
293 extern unsigned int __data_section_table_end;
294 extern unsigned int __bss_section_table;
295 extern unsigned int __bss_section_table_end;
296 extern uint32_t *__section_table_end;
297
298 // Settings struct loaded from the start of the AT24C01D I2C 1K EEPROM
299 //stEEPROM_Header_t stEEPROM_Header;
300
301 stPlatformCalls_t stPlatformCalls;
302
303 static struct netif fsl_netif1;
304 static ip4_addr_t fsl_netif1_ipaddr;
305 static ip4_addr_t fsl_netif1_netmask;
306 static ip4_addr_t fsl_netif1_gw;
307
308 typedef char tHostName[PLATFORM_HOSTNAME_MAXLEN];
309 MAKE_STRING(tHostName);
310 typedef char tSerialNo[PLATFORM_SERIAL_LEN];
311 MAKE_STRING(tSerialNo);
312
313 typedef stEEPROM_Header_t tFactoryConfig;
314
315 /*******************************************************************************
316 * GLOBAL FUNCTIONS
317 ******************************************************************************/
318
323 void BL_SysTick_DelayTicks(uint32_t n)
324 {
325 TickType_t delay = pdMS_TO_TICKS( n );
326 vTaskDelay(delay);
327 /* g_systickCounter = n;
328 while (g_systickCounter != 0U)
329 {
330 } */
331 }
332
340 int main(void)
341 {
342
343 /* Init board hardware. */
344 BOARD_ConfigMPU();
345 BOARD_InitBootPins(); // calls both BOARD_InitPins() and BOARD_InitDEBUG_UART()
346 BOARD_InitBootClocks(); // calls BOARD_BootClockRUN()
347 BOARD_InitModuleClock();
348
349 (void) REMSDAQ_UART_Init(eUartIndex_UART1, 80 * 1000000, 115200);
350
351 REMSDAQ_UART_Init(eUartIndex_UART1, 80 * 1000000, 115200);
352 printf("Remsdaq bootloader V%lu.%lu %s %s\n", VER_MAJ, VER_MIN, VER_DATE, VER_TIME);
353
354 printf("main() function @ %p\n", &main);
355
356 const CPUID_t *cpuid = (const CPUID_t *)&(SCB->CPUID);
357 printf("chip CPUID 0x%08lX @ %p\n", cpuid->R, cpuid);
358 printf("\tmanufacturer 0x%02X\n\tarchitecture 0x%X\n\tpart 0x%03X\n\tr%dp%d\n",
359 cpuid->B.implementer,
360 cpuid->B.architecture,
361 cpuid->B.partNo,
362 cpuid->B.variant,
363 cpuid->B.revision);
364 printf("Exception vector 0x%08lX\n", SCB->VTOR);
365
366
367 printf("__Vectors %p\n", __Vectors);
368 printf("__boot_hdr_start__ %p __boot_hdr_end__ %p\n", __boot_hdr_start__, __boot_hdr_end__);
369 printf("__vectors_start__ %p\n", __vectors_start__);
370 printf("__section_table_start %p __data_section_table 0x%08x __data_section_table_end 0x%08x\n",
371 __section_table_start, __data_section_table, __data_section_table_end);
372 printf("__bss_section_table 0x%08x __bss_section_table_end 0x%08x __section_table_end %p\n",
373 __bss_section_table, __bss_section_table_end, __section_table_end);
374
375 // Enable any other pins or muxes
376 IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1TxClkOutputDir, true); // enet1
377 IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET2TxClkOutputDir, true); // lwIP stack
378
379 // Initialise LPSPI1 and the SJA1105 attached to it (and the TJA1102 as well)
380 initSJA1105();
381
382 InitialiseI2CMasterClock();
383 InitialiseI2C2();
384
385 // Get module config from EEPROM
386 // Settings struct loaded from the start of the AT24C01D I2C 1K EEPROM
387 stEEPROM_Header_t stEEPROM_Header;
388 if (eeprom_header_read(&stEEPROM_Header) == false)
389 {
390 printf("Note: no EEPROM config header found, so using defaults instead.\r\n");
391 C4_displayError("EEPROM_Header not found.", C4_ERR_FILE_NOT_FOUND, true);
392 }
393 else
394 {
395 #ifdef DEBUG
396 printf("Note: EEPROM header read OK\r\n");
397 #endif
398 }
399 // need to print serial number which is an unterminated string of fixed length.
400 // The %*s or %.*s printf constructs take the length from the parameter _before_ the string parameter.
401 printf(" Remsdaq %d module \"%*s\", S/N = \"%.*s\"\r\n",
402 (int) stEEPROM_Header.u16DeviceIndex,
403 PLATFORM_HOSTNAME_MAXLEN,
404 stEEPROM_Header.achHostName,
405 PLATFORM_SERIAL_LEN,
406 stEEPROM_Header.achSerialNumber );
407
408 stack_init( &stEEPROM_Header);
409
410 xTaskCreate(C4_BootFunc, "Callisto4 Bootloader", 2048, (void *)&stEEPROM_Header, 10, NULL );
411
412 if (sys_thread_new(MAIN_THREAD_NAME, main_task, &stEEPROM_Header, MAIN_THREAD_STACKSIZE_BYTES / 4, MAIN_THREAD_PRIO) == NULL)
413 {
414 printf( "Error: unable to start main thread\r\n" );
415 }
416
417 qspifake = qspiflash_config; // Force qspiflash_config into the binary!
418 qspifake += image_vector_table; // Force image_vector_table into the binary!
419 qspifake += boot_data; // Force boot_data into the binary!
420
421 vTaskStartScheduler();
422 for (;;)
423 ;
424 }
425
426 /*******************************************************************************
427 * LOCAL FUNCTIONS
428 ******************************************************************************/
429
436 void stack_init(stEEPROM_Header_t *stEEPROM_Header)
437 {
438 ethernetif_config_t fsl_enet_config1 = {
439 .clockName = EXAMPLE_CLOCK_NAME,
440 .macAddress =
441 {
442 stEEPROM_Header->au8MACAddress[0],
443 stEEPROM_Header->au8MACAddress[1],
444 stEEPROM_Header->au8MACAddress[2],
445 stEEPROM_Header->au8MACAddress[3],
446 stEEPROM_Header->au8MACAddress[4],
447 stEEPROM_Header->au8MACAddress[5]
448 }
449 };
450 #if LWIP_DHCP
451 int err;
452 #endif
453
454 // Start tcpip_thread (lwIP) task. (Also calls lwip_init() etc.)
455 tcpip_init(NULL, NULL);
456
457 if (stEEPROM_Header->u8UseDHCP == 0)
458 {
459 IP4_ADDR(&fsl_netif1_ipaddr,
460 stEEPROM_Header->au8StaticIPAddress[0],
461 stEEPROM_Header->au8StaticIPAddress[1],
462 stEEPROM_Header->au8StaticIPAddress[2],
463 stEEPROM_Header->au8StaticIPAddress[3]);
464 IP4_ADDR(&fsl_netif1_netmask,
465 stEEPROM_Header->au8StaticNetMask[0],
466 stEEPROM_Header->au8StaticNetMask[1],
467 stEEPROM_Header->au8StaticNetMask[2],
468 stEEPROM_Header->au8StaticNetMask[3]);
469 IP4_ADDR(&fsl_netif1_gw,
470 stEEPROM_Header->au8StaticGateway[0],
471 stEEPROM_Header->au8StaticGateway[1],
472 stEEPROM_Header->au8StaticGateway[2],
473 stEEPROM_Header->au8StaticGateway[3]);
474 }
475
476 netif_add(&fsl_netif1, &fsl_netif1_ipaddr, &fsl_netif1_netmask, &fsl_netif1_gw,
477 &fsl_enet_config1, ethernetif1_init, tcpip_input);
478
479 #if LWIP_NETIF_HOSTNAME
480 netif_set_hostname(&fsl_netif1, (const char *) stEEPROM_Header->achHostName);
481 #endif
482
483 #if LWIP_IPV6
484 netif_create_ip6_linklocal_address(&fsl_netif1, 1); // LWIP_IPV6
485 // netif_ip6_addr_set_state((&EMAC_if), 0, IP6_ADDR_TENTATIVE); LWIP_IPV6 Don't think I need to do this...
486 #endif
487
488 netif_set_default(&fsl_netif1);
489
490 // Note: according to https://www.nongnu.org/lwip/2_1_x/sys_init.html ...
491 // ...we should add the following call in here: (NickP)
492 // netif_set_link_up(&fsl_netif1);
493
494 netif_set_up(&fsl_netif1);
495
496 if (stEEPROM_Header->u8UseDHCP != 0)
497 {
498 #if LWIP_DHCP
499 err = dhcp_start(&fsl_netif1);
500 LWIP_PLATFORM_DIAG(( "dhcp_start...........[result=%d]\r\n", err ));
501 #else
502 LWIP_PLATFORM_DIAG(( "Error: DHCP enabled but not compiled in\r\n" ));
503 #endif
504 }
505
506 printf("\r\n************************************************\r\n");
507 printf(" Remsdaq %d module, S/N = %s\r\n",
508 (int) stEEPROM_Header->u16DeviceIndex,
509 stEEPROM_Header->achSerialNumber );
510 printf(" MAC Address : %02X:%02X:%02X:%02X:%02X:%02X\r\n",
511 (int) fsl_enet_config1.macAddress[0],
512 (int) fsl_enet_config1.macAddress[1],
513 (int) fsl_enet_config1.macAddress[2],
514 (int) fsl_enet_config1.macAddress[3],
515 (int) fsl_enet_config1.macAddress[4],
516 (int) fsl_enet_config1.macAddress[5]);
517
518 if (stEEPROM_Header->u8UseDHCP == 0)
519 {
520 // No DHCP, so display static IP address
521 ipaddress_show(stEEPROM_Header);
522 }
523
524 #if LWIP_IPV6
525 printf(" IPv6 Link Local Address : %s\r\n", ip6addr_ntoa(&(fsl_netif1.ip6_addr[0].u_addr.ip6)) );
526 #endif
527 printf("************************************************\r\n");
528
529 #if STACK_INIT_USE_TASK
530 vTaskDelete(NULL);
531 #endif
532 }
533
537 void ipaddress_show(stEEPROM_Header_t *stEEPROM_Header)
538 {
539 printf(" IPv4 Address : %u.%u.%u.%u\r\n",
540 (unsigned int)((u8_t *)&fsl_netif1_ipaddr)[0],
541 (unsigned int)((u8_t *)&fsl_netif1_ipaddr)[1],
542 (unsigned int)((u8_t *)&fsl_netif1_ipaddr)[2],
543 (unsigned int)((u8_t *)&fsl_netif1_ipaddr)[3]);
544 printf(" IPv4 Subnet mask : %u.%u.%u.%u\r\n",
545 (unsigned int)((u8_t *)&fsl_netif1_netmask)[0],
546 (unsigned int)((u8_t *)&fsl_netif1_netmask)[1],
547 (unsigned int)((u8_t *)&fsl_netif1_netmask)[2],
548 (unsigned int)((u8_t *)&fsl_netif1_netmask)[3]);
549 printf(" IPv4 Gateway : %u.%u.%u.%u\r\n",
550 (unsigned int)((u8_t *)&fsl_netif1_gw)[0],
551 (unsigned int)((u8_t *)&fsl_netif1_gw)[1],
552 (unsigned int)((u8_t *)&fsl_netif1_gw)[2],
553 (unsigned int)((u8_t *)&fsl_netif1_gw)[3]);
554 }
555
561 void main_task(void *pvParam)
562 {
563 stEEPROM_Header_t *stEEPROM_Header = (stEEPROM_Header_t *)pvParam;
564
565 bool bHasIPAddr = (stEEPROM_Header->u8UseDHCP == 0);
566 int iCount;
567
568 if (pvParam) { } // Unused parameter
569
570 vTaskDelay( 250 ); // Sleep for 250 msec
571
572 for (iCount = 0; ; iCount++)
573 {
574 vTaskDelay( 250 ); // Sleep for 250 msec
575 #if 0
576 // Note: according to https://www.nongnu.org/lwip/2_1_x/sys_init.html ...
577 // ...we should periodically call sys_check_timeouts() to keep TCPIP/LWIP happy
578 // However, Jeremy says the tcpip task already calls this - CHECK THIS!
579 sys_check_timeouts();
580 #endif
581
582 // tasks_debug();
583
584 if (bHasIPAddr == false)
585 {
586 #if LWIP_DHCP
587 // Has DHCP supplied us an address yet?
588 if (dhcp_supplied_address(&fsl_netif1))
589 {
590 bHasIPAddr = true;
591 // Yes, DHCP has supplied an IP address etc, so display dynamic IP address
592 ipaddress_show(stEEPROM_Header);
593 }
594 #else
595 bHasIPAddr = true;
596 #endif
597 }
598 }
599 }
600
606 void BOARD_InitModuleClock(void)
607 {
608 const clock_enet_pll_config_t config = {.enableClkOutput = true, .enableClkOutput25M = true, .loopDivider = 1, .enableClkOutput1 = true, .loopDivider1 = 1};
609 CLOCK_InitEnetPll(&config);
610 }
611
612 static void C4_BootFunc(void *pParams)
613 {
614 stEEPROM_Header_t *stEEPROM_Header = (stEEPROM_Header_t *)pParams;
615
616 exit_code_t rc = C4_ERR_OK;
617
618 #ifdef TEST_ASM
619 asm_test();
620 #endif
621
622
623 #ifdef TEST_EXCEP
624 excep_test();
625 #endif
626
627 #ifdef TEST_QSPI
628 // call test before C4_QSPI_init().
629 rc = QSPI_test();
630 C4_displayError("QSPI test", rc, true);
631 #endif
632
633 #ifdef TEST_WATCHDOG
634 bl_api_init();
635 rc = watchdog_test();
636 C4_displayError("Watchdog test", rc, true);
637 #else
638 // c4_initWatchdog(C4_WDOG1, 1275, 20);
639 // c4_getResetHistory();
640 # ifdef TEST_WATCHDOG_IF
641 rc = watchdog_if_test(C4_WDOG1);
642 C4_displayError("Watchdog interface test", rc, true);
643 # endif
644 #endif
645
646 #ifdef TEST_SVC
647 rc = SVC_test();
648 C4_displayError("SVC test", rc, true);
649 #endif
650
651 #ifdef TEST_PRIVILEGE
652 rc = TestUnprivileged();
653 C4_displayError("", rc, false);
654 #endif
655
656 // Make sure that the QSPI interface is initialised
657 rc = C4_QSPI_init();
658 C4_displayError("", rc, true);
659
660 const char *const config_addr = (const char *const) QSPI_BOOTLOADERx_CONFIG;
661
662 char args[BUF_LEN];
663 const serialNOR_t *location[2] = {0,0};
664
665 if (C4_ERR_OK == (rc = GetConfig(config_addr, BUF_LEN, C4_BOOT_CONFIG_PARSER_CURRENT, args)))
666 {
667 sscanf(args, "%p", &location[CURRENT]);
668 C4_PRINT("Got current location %p\n", location[CURRENT]);
669 }
670 else if (C4_ERR_FILE_NOT_FOUND == rc)
671 {
672 C4_PRINT("Missing config @%p %d\n", config_addr, rc);
673 char file[1024];
674 rc = c4_tftpDownloadText(stEEPROM_Header->au8StaticIPAddress, "CallistoBootloader_data.txt", config_addr, QSPI_BOOTLOADER_CONFIG_SIZE);
675 }
676 else
677 {
678 C4_PRINT("Bad config @%p %d\n", config_addr, rc);
679 }
680 C4_displayError("", rc, true);
681
682 if (C4_ERR_OK == (rc = GetConfig(config_addr, BUF_LEN, C4_BOOT_CONFIG_PARSER_RECOVERY, args)))
683 {
684 sscanf(args, "%p", &location[RECOVERY]);
685 C4_PRINT("Got recovery location %p\n", location[RECOVERY]);
686 }
687 else
688 {
689 C4_PRINT("Bad config @%p %d\n", config_addr, rc);
690 }
691
692 C4_displayError("", rc, true);
693
694 if (C4_ERR_OK == (rc = GetConfig(config_addr, BUF_LEN, C4_BOOT_CONFIG_PARSER_ARGS, args)))
695 {
696 C4_PRINT("Got args \"%s\"\n", args);
697 }
698 else
699 {
700 C4_PRINT("Bad config @%p %d\n", config_addr, rc);
701 }
702
703 C4_displayError("", rc, true);
704
705 if (C4_ERR_OK == (rc = C4_checkExecutable(location[CURRENT])))
706 {
707 char newval[11] = {'\0'};
708 sprintf(newval,"%p", location[CURRENT]);
709 rc = SetConfig(config_addr, BUF_LEN, C4_BOOT_CONFIG_PARSER_FAULTY, newval, E_REMOVE);
710
711 // For test purposes toggle locations:
712 if (location[RECOVERY]){
713 sprintf(newval,"%p", location[RECOVERY]);
714 rc = SetConfig(config_addr, BUF_LEN, C4_BOOT_CONFIG_PARSER_CURRENT, newval, E_REPLACE);
715 sprintf(newval,"%p", location[CURRENT]);
716 rc = SetConfig(config_addr, BUF_LEN, C4_BOOT_CONFIG_PARSER_RECOVERY, newval, E_REPLACE);
717 }
718
719 C4_displayVectorTable("Current", *(location + CURRENT));
720 C4_PRINT("Jumping to %p\n", (uint8_t *)location[CURRENT]);
721
722 C4_jumpToUserApplication((uint32_t)location[CURRENT], args);
723 }
724 else
725 {
726 C4_displayError("Current image bad", rc, false);
727 char newval[11] = {'\0'};
728 sprintf(newval,"%p", location[CURRENT]);
729 rc = SetConfig(config_addr, BUF_LEN, C4_BOOT_CONFIG_PARSER_FAULTY, newval, E_EXTEND);
730 }
731
732 if (C4_ERR_OK == (rc = C4_checkExecutable(location[RECOVERY])))
733 {
734 // Set recovery as current image until we decide on a mechanism
735 // to mark the current faulty.
736 {
737 char newval[11] = {'\0'};
738 sprintf(newval,"%p", location[RECOVERY]);
739 rc = SetConfig(config_addr, BUF_LEN, C4_BOOT_CONFIG_PARSER_CURRENT, newval, E_REPLACE);
740 sprintf(newval,"%p", location[CURRENT]);
741 rc = SetConfig(config_addr, BUF_LEN, C4_BOOT_CONFIG_PARSER_RECOVERY, newval, E_REPLACE);
742 }
743 C4_displayVectorTable("Recovery", *(location + RECOVERY));
744
745 C4_PRINT("Jumping to %p\n", (uint8_t *)location[RECOVERY]);
746
747 C4_jumpToUserApplication((uint32_t)location[RECOVERY], args);
748 }
749 else
750 {
751 C4_displayError("Recovery image bad", rc, false);
752 char newval[11] = {'\0'};
753 sprintf(newval,"%p", location[RECOVERY]);
754 rc = SetConfig(config_addr, BUF_LEN, C4_BOOT_CONFIG_PARSER_FAULTY, newval, E_EXTEND);
755
756 }
757
758 while (1)
759 {
760 FlashLed(E_RED, 100U, 100U);
761 FlashLed(E_YELLOW, 50U, 50U);
762 FlashLed(E_GREEN, 50U, 50U);
763 }
764
765 // Task shouldn't return, but should't get here either.
766 vTaskDelete( NULL );
767 }
768
769 /*
770 * ============================================================================
771 */
772
773
774 static void C4_jumpToUserApplication(uint32_t app_start, const char *args)
775 {
776 C4_PRINT("%s (user_sp %p, user_start %p)\n", __FUNCTION__,
777 (void *)(*(uint32_t *)(app_start)),
778 (void *)(*((uint32_t *)(app_start+4))));
779
780 /* Invalidate caches */
781 SCB_DisableDCache();
782 SCB_DisableICache();
783 /* The main application will enable caches */
784 __DMB();
785
786 /* Relocate vector table */
787 SCB->VTOR = app_start;
788
789 C4_jump(*(uint32_t *)(app_start), *((uint32_t *)(app_start+4)), args);
790 }
791
792 /*
793 * ============================================================================
794 */
795 static void C4_jump(uint32_t user_sp, uint32_t user_startup, const char *argv)
796 {
797 int argc = 0;
798 const char *ptr = argv;
799 while((ptr = strpbrk(ptr, " ")) != NULL)
800 {
801 ++argc;
802 ++ptr;
803 }
804
805 const char *const start_log = (const char *const) QSPI_BOOTLOADERy_CONFIG;
806
807 // Read HPRTCMR and HPRTCLR - 15 bits and 32 bits respectively
808 // Combined 47 bits max value 140,737,488,355,327
809 // The exact maximum time in seconds depends on the value set in HPCR and the tick rate.
810 SNVS_Type *pSNVS = SNVS;
811
812 uint32_t seconds = 0, tmp = 0;
813 do
814 {
815 // keep reading until consecutive reads match
816 seconds = tmp;
817 tmp = ((pSNVS->HPRTCMR << 17) | (pSNVS->HPRTCLR >> 15));
818 } while (seconds != tmp);
819
820 char str[32] = "\0";
821 sprintf(str, "START @ %ld\n", seconds);
822 uintptr_t dst = strlen(start_log);
823
824 C4_QSPI_write((uintptr_t)(start_log+dst), strlen(str), (const uint8_t *)str);
825
826 // Create the function call to the user application.
827 // Static variables are needed since changed the stack pointer out from under the compiler
828 // we need to ensure the values we are using are not stored on the previous stack
829 static uint32_t s_stackPointer = 0;
830 s_stackPointer = user_sp;
831 static void (*farewell_bootloader)(int, const char *) = 0;
832 farewell_bootloader = (void (*)(int, const char *))user_startup;
833
834 // Set stack pointers to the application stack pointer.
835 __set_MSP(s_stackPointer);
836 __set_PSP(s_stackPointer);
837
838 // Jump to the application.
839 farewell_bootloader(argc, argv);
840 }
841
842 /*
843 * ============================================================================
844 */
845 static exit_code_t C4_checkExecutable(const serialNOR_t *image)
846 {
847 exit_code_t rc = C4_ERR_OK;
848
849 if (0xFFFFFFFF == image->memCfg.tag)
850 rc = C4_ERR_IMAGE_CORRUPT;
851 else if (0x42464346 == image->memCfg.tag)
852 rc = C4_ERR_IMAGE_BOOTABLE;
853
854 return rc;
855 }
856
857 /*
858 * ============================================================================
859 */
860 static void C4_displayVectorTable(const char *identifier, const serialNOR_t *table)
861 {
862 C4_PRINT("Using %s image at %p\n", identifier, table);
863 C4_PRINT("IVT_offset 0x%08x\n", IVT_offset);
864 const IVT_t * const IVT = (const IVT_t *const)((uint8_t *)table + IVT_offset);
865 C4_PRINT("Got IVT @%p\n", IVT);
866 C4_PRINT("\theader 0x%08lx\n", IVT->header.R);
867 C4_PRINT("\tentry 0x%08lx\n", IVT->entry);
868 C4_PRINT("\treserved 0x%08lx\n", IVT->reserved1);
869 C4_PRINT("\tdcd 0x%08lx\n", IVT->dcd);
870 C4_PRINT("\tbootdata 0x%08lx\n", IVT->bootData);
871 C4_PRINT("\tself 0x%08lx\n", IVT->self);
872 C4_PRINT("\tcsf 0x%08lx\n", IVT->csf);
873 C4_PRINT("\treserved 0x%08lx\n", IVT->reserved2);
874 }
875
876
882 void BOARD_InitLPSPI3(void)
883 {
884 IOMUXC_SetPinMux(
885 IOMUXC_GPIO_AD_B1_15_LPSPI3_SCK, /* GPIO_AD_B1_15 is configured as LPSPI3_SCK */
886 0U); /* Software Input On Field: Input Path is determined by functionality */
887 IOMUXC_SetPinMux(
888 IOMUXC_GPIO_AD_B1_12_LPSPI3_PCS0, /* GPIO_AD_B1_12 is configured as LPSPI3_PCS0 */
889 0U); /* Software Input On Field: Input Path is determined by functionality */
890 IOMUXC_SetPinMux(
891 IOMUXC_GPIO_AD_B1_14_LPSPI3_SDO, /* GPIO_AD_B1_14 is configured as LPSPI3_SDO */
892 0U); /* Software Input On Field: Input Path is determined by functionality */
893 IOMUXC_SetPinMux(
894 IOMUXC_GPIO_AD_B1_13_LPSPI3_SDI, /* GPIO_AD_B1_13 is configured as LPSPI3_SDI */
895 0U); /* Software Input On Field: Input Path is determined by functionality */
896
897 IOMUXC_SetPinConfig(
898 IOMUXC_GPIO_AD_B1_15_LPSPI3_SCK, /* GPIO_SD_B0_00 PAD functional properties : */
899 0x10B0u); /* Slew Rate Field: Slow Slew Rate
900 Drive Strength Field: R0/6
901 Speed Field: medium(100MHz)
902 Open Drain Enable Field: Open Drain Disabled
903 Pull / Keep Enable Field: Pull/Keeper Enabled
904 Pull / Keep Select Field: Keeper
905 Pull Up / Down Config. Field: 100K Ohm Pull Down
906 Hyst. Enable Field: Hysteresis Disabled */
907 IOMUXC_SetPinConfig(
908 IOMUXC_GPIO_AD_B1_12_LPSPI3_PCS0, /* GPIO_SD_B0_01 PAD functional properties : */
909 0x10B0u); /* Slew Rate Field: Slow Slew Rate
910 Drive Strength Field: R0/6
911 Speed Field: medium(100MHz)
912 Open Drain Enable Field: Open Drain Disabled
913 Pull / Keep Enable Field: Pull/Keeper Enabled
914 Pull / Keep Select Field: Keeper
915 Pull Up / Down Config. Field: 100K Ohm Pull Down
916 Hyst. Enable Field: Hysteresis Disabled */
917 IOMUXC_SetPinConfig(
918 IOMUXC_GPIO_AD_B1_14_LPSPI3_SDO, /* GPIO_SD_B0_02 PAD functional properties : */
919 0x10B0u); /* Slew Rate Field: Slow Slew Rate
920 Drive Strength Field: R0/6
921 Speed Field: medium(100MHz)
922 Open Drain Enable Field: Open Drain Disabled
923 Pull / Keep Enable Field: Pull/Keeper Enabled
924 Pull / Keep Select Field: Keeper
925 Pull Up / Down Config. Field: 100K Ohm Pull Down
926 Hyst. Enable Field: Hysteresis Disabled */
927 IOMUXC_SetPinConfig(
928 IOMUXC_GPIO_AD_B1_13_LPSPI3_SDI, /* GPIO_SD_B0_03 PAD functional properties : */
929 0x10B0u); /* Slew Rate Field: Slow Slew Rate
930 Drive Strength Field: R0/6
931 Speed Field: medium(100MHz)
932 Open Drain Enable Field: Open Drain Disabled
933 Pull / Keep Enable Field: Pull/Keeper Enabled
934 Pull / Keep Select Field: Keeper
935 Pull Up / Down Config. Field: 100K Ohm Pull Down
936 Hyst. Enable Field: Hysteresis Disabled */
937 }
VER_TIME
static const char *const VER_TIME
Compilation time.
Definition: bootloader.c:162
__vectors_start__
uint32_t * __vectors_start__
NULL
#define NULL
Definition: bootloader_common.h:26
SCB_DisableDCache
__STATIC_FORCEINLINE void SCB_DisableDCache(void)
Disable D-Cache.
Definition: core_cm7.h:2328
IVT_t::dcd
uint32_t dcd
Definition: bootloader_types.h:199
__boot_hdr_start__
uint32_t __boot_hdr_start__[]
IVT_t::entry
uint32_t entry
Definition: bootloader_types.h:197
InitialiseI2C2
void InitialiseI2C2(void)
Initialise the I2C2 device.
Definition: platform_eeprom.c:171
clock_config.h
BOARD_InitLPSPI3
void BOARD_InitLPSPI3(void)
Definition: bootloader.c:875
__boot_hdr_end__
uint32_t __boot_hdr_end__[]
IVT_t::csf
uint32_t csf
Definition: bootloader_types.h:203
CPUID_t
structure for CPU ID base register in System Control Block (SCB).
Definition: bootloader.c:186
coap_join_group
void coap_join_group(stEEPROM_Header_t *stEEPROM_Header)
C4_jumpToUserApplication
static void C4_jumpToUserApplication(uint32_t app_start, const char *args)
Set up jump and arguments.
Definition: bootloader.c:767
IVT_t::header
union IVT_t::@120 header
BUF_LEN
static const uint32_t BUF_LEN
Definition: bootloader.c:173
ipaddress_show
void ipaddress_show(stEEPROM_Header_t *stEEPROM_Header)
Definition: bootloader.c:530
C4_PRINT
#define C4_PRINT(...)
Definition: bootloader.c:153
watchdog_test
exit_code_t watchdog_test()
Test function for watchdog 1.
Definition: watchdog_test.c:56
tFactoryConfig
stEEPROM_Header_t tFactoryConfig
Definition: bootloader.c:308
bl_api_init
void bl_api_init(void)
Definition: bl_api.c:20
SCB_DisableICache
__STATIC_FORCEINLINE void SCB_DisableICache(void)
Disable I-Cache.
Definition: core_cm7.h:2255
IVT_t::reserved2
uint32_t reserved2
Definition: bootloader_types.h:205
fsl_netif1_gw
static ip4_addr_t fsl_netif1_gw
Definition: bootloader.c:301
FlexSPI_Header_t::tag
uint32_t tag
Definition: bootloader_types.h:27
__data_section_table_end
unsigned int __data_section_table_end
fsl_netif1_ipaddr
static ip4_addr_t fsl_netif1_ipaddr
Definition: bootloader.c:299
CURRENT
static const uint32_t CURRENT
Index in jump location array for currant image.
Definition: bootloader.c:169
c4_error_codes.h
Enumeration of Error Codes.
__bss_section_table_end
unsigned int __bss_section_table_end
SNVS_Type
Definition: MIMXRT1062.h:37701
CPUID_t::R
uint32_t R
Definition: bootloader.c:195
VER_MIN
static const uint32_t VER_MIN
Minor version number.
Definition: bootloader.c:158
__DMB
__STATIC_FORCEINLINE void __DMB(void)
Data Memory Barrier.
Definition: cmsis_gcc.h:888
__set_PSP
__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
Set Process Stack Pointer.
Definition: cmsis_armcc.h:206
__data_section_table
unsigned int __data_section_table
fsl_device_registers.h
IVT_t::bootData
uint32_t bootData
Definition: bootloader_types.h:201
qspiflash_config
char qspiflash_config
SetConfig
exit_code_t SetConfig(const char *mem, uint32_t mem_len, E_parseIndices_t field, const char *val, file_op_t op)
Set value in the specified memory location.
Definition: c4_parser.c:221
TestUnprivileged
exit_code_t TestUnprivileged()
Test unprivileged mode.
Definition: c4_privilege_modes_test.c:57
VER_MAJ
static const uint32_t VER_MAJ
Major version number.
Definition: bootloader.c:156
__section_table_start
uint32_t * __section_table_start
tHostName
char tHostName[PLATFORM_HOSTNAME_MAXLEN]
Definition: bootloader.c:303
E_EXTEND
Definition: c4_parser.h:74
asm_test
void asm_test(void)
__Vectors
uint32_t __Vectors[]
eeprom_header_setdefaults
void eeprom_header_setdefaults(stEEPROM_Header_t *pstHeader)
Set the local defaults to use if the EEPROM header couldn't be read in.
C4_QSPI_write
exit_code_t C4_QSPI_write(uintptr_t addr, size_t len, const uint8_t *pData)
Write data to QSPI flash memory.
Definition: c4_qspi.c:230
c4_qspi.h
Interface to QSPI Flash.
BOARD_InitBootClocks
void BOARD_InitBootClocks(void)
This function executes default configuration of clocks.
Definition: clock_config.c:39
VER_DATE
static const char *const VER_DATE
Compilation date.
Definition: bootloader.c:160
exit_code_t
exit_code_t
Enumeration of error codes.
Definition: c4_error_codes.h:96
EXAMPLE_CLOCK_NAME
#define EXAMPLE_CLOCK_NAME
Definition: bootloader.c:176
RegisterFactoryConfig
void RegisterFactoryConfig(void)
serialNOR_t
Serial NOR configuration block Contains FlexSPIheader common block and NOR specific configuration.
Definition: bootloader_types.h:150
IVT_t::self
uint32_t self
Definition: bootloader_types.h:202
excep_test
int excep_test(void)
Definition: excep_test.c:28
SNVS_Type::HPRTCLR
__IO uint32_t HPRTCLR
Definition: MIMXRT1062.h:37712
SNVS_Type::HPRTCMR
__IO uint32_t HPRTCMR
Definition: MIMXRT1062.h:37711
CPUID_t::B
struct CPUID_t::@111 B
__set_MSP
__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
Set Main Stack Pointer.
Definition: cmsis_armcc.h:230
C4_checkExecutable
static exit_code_t C4_checkExecutable(const serialNOR_t *image)
Check whether an executable exists at the location and is valid.
Definition: bootloader.c:838
stPlatformCalls
stPlatformCalls_t stPlatformCalls
Definition: bootloader.c:296
E_REMOVE
Definition: c4_parser.h:75
pin_mux.h
eeprom_header_read
bool eeprom_header_read(stEEPROM_Header_t *pstHeader)
Read an EEPROM platform configuration block.
Definition: platform_eeprom.c:92
CPUID_t::architecture
uint32_t architecture
Reads as 0xF.
Definition: bootloader.c:192
stack_init
void stack_init(stEEPROM_Header_t *stEEPROM_Header)
Initialise the IP stack.
Definition: bootloader.c:429
__bss_section_table
unsigned int __bss_section_table
InitialiseI2CMasterClock
void InitialiseI2CMasterClock(void)
Initialise the I2C master clock.
Definition: platform_eeprom.c:159
C4_jump
static void C4_jump(uint32_t user_sp, uint32_t user_startup, const char *argv)
Jump to application.
Definition: bootloader.c:788
CPUID_t::revision
uint32_t revision
CPU revision.
Definition: bootloader.c:190
IVT_t::R
uint32_t R
Register representation.
Definition: bootloader_types.h:195
CPUID_t::implementer
uint32_t implementer
Implementer code reads as 0x41 for processor implemented by ARM.
Definition: bootloader.c:194
FlashLed
void FlashLed(colour_t led, unsigned int on, unsigned int off)
Flash the led in the specified colour.
Definition: c4_colours.c:55
serialNOR_t::memCfg
FlexSPI_Header_t memCfg
Definition: bootloader_types.h:152
SNVS
#define SNVS
Definition: MIMXRT1062.h:38773
QSPI_test
exit_code_t QSPI_test(void)
Run through a set of read and write tests on QSPI Flash.
Definition: c4_qspi_test.c:89
BL_SysTick_DelayTicks
void BL_SysTick_DelayTicks(uint32_t n)
Sets a delay.
Definition: bootloader.c:317
fsl_netif1_netmask
static ip4_addr_t fsl_netif1_netmask
Definition: bootloader.c:300
bootloader_types.h
Type defintions used by the bootloader.
main
int main(void)
Application entry point.
Definition: bootloader.c:334
C4_displayError
void C4_displayError(const char *text, exit_code_t errVal, bool fatal)
Print exit code on serial line and flash led.
Definition: c4_error_codes.c:44
C4_WDOG1
Watchdog 1 - resets processor.
Definition: c4_watchdog.h:39
fsl_netif1
static struct netif fsl_netif1
Definition: bootloader.c:298
MAIN_THREAD_STACKSIZE_BYTES
#define MAIN_THREAD_STACKSIZE_BYTES
Definition: bootloader.c:179
BOARD_ConfigMPU
void BOARD_ConfigMPU(void)
Definition: board.c:233
image_vector_table
char image_vector_table
IOMUXC_GPR
#define IOMUXC_GPR
Definition: MIMXRT1062.h:24372
RECOVERY
static const uint32_t RECOVERY
Definition: bootloader.c:170
config_addr
const char *const config_addr
board.h
IVT_t::reserved1
uint32_t reserved1
Definition: bootloader_types.h:198
CPUID_t::variant
uint32_t variant
Variant number.
Definition: bootloader.c:193
main_task
void main_task(void *pvParam)
Definition: bootloader.c:554
IVT_offset
static const ptrdiff_t IVT_offset
fixed offset of IVT in program image region.
Definition: bootloader.c:165
C4_QSPI_init
exit_code_t C4_QSPI_init(void)
Initialise the flexSPI interface to QSPI.
Definition: c4_qspi.c:74
BOARD_InitBootPins
void BOARD_InitBootPins(void)
Calls initialization functions.
Definition: pin_mux.c:33
SVC_test
exit_code_t SVC_test()
Definition: c4_svc_test.c:35
CPUID_t::partNo
uint32_t partNo
CPU part number.
Definition: bootloader.c:191
MAKE_STRING
MAKE_STRING(tHostName)
MAIN_THREAD_PRIO
#define MAIN_THREAD_PRIO
Definition: bootloader.c:180
GetConfig
exit_code_t GetConfig(const char *mem, uint32_t mem_len, E_parseIndices_t field, char *pVal)
Parse the specified memory location.
Definition: c4_parser.c:139
tSerialNo
char tSerialNo[PLATFORM_SERIAL_LEN]
Definition: bootloader.c:305
qspifake
volatile char qspifake
Definition: bootloader.c:277
c4_parser.h
Interface to simple parser.
c4_tftp.h
Functions to connect to an TFTP server and download application files and configurations.
SCB
#define SCB
Definition: core_armv81mml.h:2043
C4_BootFunc
static void C4_BootFunc(void *pParam)
Definition: bootloader.c:605
__section_table_end
uint32_t * __section_table_end
BOARD_InitModuleClock
void BOARD_InitModuleClock(void)
Definition: bootloader.c:599
watchdog_if_test
exit_code_t watchdog_if_test(c4_wdog_t wdog)
Test Callisto 4 watchdog interfaces.
Definition: watchdog_test.c:166
C4_displayVectorTable
static void C4_displayVectorTable(const char *identifier, const serialNOR_t *table)
Print out vector table.
Definition: bootloader.c:853
IVT_t
Structure to overlay on Image Vector Table.
Definition: bootloader_types.h:183
boot_data
char boot_data
MAIN_THREAD_NAME
#define MAIN_THREAD_NAME
Definition: bootloader.c:178
c4_tftpDownloadText
exit_code_t c4_tftpDownloadText(const uint8_t server[4], const char *name, char *file, uint32_t max_file)
Use TFTP to download the configuration file.
Definition: c4_tftp.c:266
E_REPLACE
Definition: c4_parser.h:72