Wilkins White

Guide to Porting MCUBOOT v2 to MCUXpresso

Discussion created by Wilkins White on Jul 9, 2018
Latest reply on Jul 10, 2018 by Alice_Yang

Introduction

This post will describe the process for building and using the NXP Kinetis Bootloader version 2.0.0 with the MCUXpresso IDE and SDK.  This guide assumes you are familiar with creating and running projects using MCUXpresso and have installed the SDK for your target processor.  This procedure is tested and working with the MKV56F24.

 

Project Setup

  1.  Download the source package from MCU Bootloader|NXP 
  2. Create a new C project in MCUXpresso for your processor with the following drivers:
    • Required for core function:
      • clock
      • port
      • gpio
      • crc
    • Optional depending on configuration:
      • flexcan
      • uart
      • dspi
      • i2c
  3. Delete the template 'main' file that MCUXpresso creates for you.
  4. Delete the semihost_hardfault.c file that MCUXpresso creates for you.
  5. Create driver sub-folders and move the driver source into them
    • move fsl_port.c/h into drivers/port
    • move fsl_gpio.c/h into drivers/gpio
    • move fsl_crc.c/h into drivers/crc
    • move fsl_dspi.c/h into drivers/dspi
    • move fsl_flexcan.c/h into drivers/flexcan
    • move fsl_i2c.c/h into drivers/i2c
    • move fsl_uart.c/h into drivers/uart
  6. Unzip the bootloader source
  7. Copy the contents of the NXP_Kinetis_Bootloader_2_0_0/src directory to your new project's source directory.
  8. Copy the contents of the NXP_Kinetis_Bootloader_2_0_0/targets/common/src directory to your new project's source directory
  9. Refresh the project so MCUXpresso becomes aware of the new source
  10. Delete or filter out the following directories from the bootloader source:
    • source/blfwk
    • source/blsh
    • source/bm_usb
    • source/platform
    • source/usb
    • source/security
  11. Delete or filter out the following sources
    • source/startup/boot.s
    • source/startup/crt0.s
    • source/startup/ar_handlers_cm0p.S
    • source/memory/src/pattern_fill.s
    • source/memory/src/qspi_memory.c
    • source/memory/src/qspi_memory.h
    • source/utilities/src/bootloader_tree_stub.c
    • source/bootloader/src/bl_flashloader.c
    • source/bootloader/src/bl_misc_rom.c
    • source/bl_lpi2c_irq_config_common.c
    • source/bl_lpspi_irq_config_common.c
    • source/bl_spuart_irq_config_common.c
    • source/bl_intmux_irq.c
    • source/clock_common_scg.c
  12. Delete or filter out the following interfaces
    • source/bootloader/src/lpspi_peripheral_interface.c
    • source/bootloader/src/lpi2c_peripheral_interface.c
    • source/bootloader/src/lpuart_peripheral_interface.c
    • source/bootloader/src/spi_peripheral_interface.c
    • source/bootloader/src/usb_hid_msc_peripheral_interface.c
    • source/bootloader/src/usb_hid_peripheral_interface.c
    • source/bootloader/src/usb_hs_hid_peripheral_interface.c
    • source/bootloader/src/uart0_peripheral_interface.c
  13. Choose an sram initialization based on your processor and filter/delete the other two:
    • source/memory/src/sram_init_cm0plus.c
    • source/memory/src/sram_init_cm4.c
    • source/memory/src/sram_init_cm7.c
  14. Delete or filter out the following drivers in favor of the SDK versions
    • source/drivers/common
    • source/drivers/crc
    • source/drivers/dspi
    • source/drivers/flexcan
    • source/drivers/gpio
    • source/drivers/i2c
    • source/drivers/intmux
    • source/drivers/lpi2c
    • source/drivers/lpsci
    • source/drivers/lpspi
    • source/drivers/lpuart
    • source/drivers/ltc
    • source/drivers/mmcau
    • source/drivers/otfad
    • source/drivers/port
    • source/drivers/qspi
    • source/drivers/spi
    • source/drivers/uart
    • source/drivers/watchdog
    • source/drivers/wdog32
  15. Choose the microseconds back-end appropriate for your processor and delete the other:
    • source/drivers/microseconds/src/microseconds_pit.c
    • source/drivers/microseconds/src/microseconds_sysclk.c
  16. Add the following paths to the project "GNU C" includes:
    • source/include
    • source/drivers
  17. Define the following symbols
SymbolValue
__DATA_RAM_data
__DATA_ROM_etext
__START_BSS_bss
__END_BSS_ebss
__STACK_TOP_vStackTop
__VECTOR_RAM__vectors_start__
__VECTOR_TABLE__vectors_start__

 

If the processor is a Cortex M7 you should additionally define

SymbolValue
CPU_IS_ARM_CORTEX_M71

 

Source Modification

Now that the source has been pruned we need to apply a few modifications to account for the new memory layout and linker files in MCUXpresso.

 

source/startup/crt0_gcc.S

@@ -43,10 +43,10 @@
         .extern SystemInit
         .extern init_data_bss
         .extern main
-        .extern __StackTop
+        .extern _vStackTop
         .extern init_interrupts
 
-        .extern __isr_vector
+        .extern g_pfnVectors
 
 
 #define SCS_BASE            (0xE000E000)                            /*!< System Control Space Base Address */
@@ -59,7 +59,7 @@ Reset_Handler:
         cpsid   i
 
         // Set VTOR register in SCB first thing we do.
-        ldr     r0,=__isr_vector
+        ldr     r0,=g_pfnVectors
         ldr     r1,=SCB_BASE
         str     r0,[r1, #SCB_VTOR_OFFSET]
 
@@ -77,7 +77,7 @@ Reset_Handler:
         mov     r12,r7
 
         // Initialize the stack pointer
-        ldr     r0,=__StackTop
+        ldr     r0,=_vStackTop
         mov     r13,r0

 

source/startup/startup.c

@@ -97,10 +97,10 @@ void init_data_bss(void)
 #if defined(__GNUC__)
     extern uint32_t __DATA_ROM[];
     extern uint32_t __DATA_RAM[];
-    extern char __DATA_END[];
+    extern uint32_t _edata[];
     data_ram = (uint8_t *)__DATA_RAM;
     data_rom = (uint8_t *)__DATA_ROM;
-    data_rom_end = (uint8_t *)__DATA_END; // This is actually a RAM address in CodeWarrior
+    data_rom_end = (uint8_t *)(__DATA_ROM + (_edata - __DATA_RAM));
     n = data_rom_end - data_rom;
 #elif(defined(__ICCARM__))
     data_ram = __section_begin(".data");

source/property/src/property.c

@@ -75,14 +75,16 @@ extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Limit[];
#define __ROM_START ((uint32_t)Image$$VECTOR_ROM$$Base)
#define __ROM_END ((uint32_t)Image$$ER_m_text$$Limit)
#elif(defined(__GNUC__)) // GCC
-extern uint32_t __VECTOR_RAM[];
extern uint32_t __VECTOR_TABLE[];
-extern char __DATA_END[];
+extern uint32_t __DATA_ROM[];
+extern uint32_t __DATA_RAM[];
+extern uint32_t _edata[];
extern uint32_t __STACK_TOP[];
-#define __RAM_START ((uint32_t)__VECTOR_RAM)
-#define __RAM_END ((uint32_t)__STACK_TOP - 1)
+extern uint32_t __top_RAM[];
+#define __RAM_START ((uint32_t)__STACK_TOP - 1)
+#define __RAM_END ((uint32_t)__top_RAM)
#define __ROM_START ((uint32_t)__VECTOR_TABLE)
-#define __ROM_END ((uint32_t)__DATA_END)
+#define __ROM_END ((uint32_t)(__DATA_ROM + (_edata - __DATA_RAM)))
#else
#error Unknown toolchain!
#endif // __ICCARM__

Configuration

Now we need to add the processor specific configuration. Create/import the following files for your device according to section 10 of the MCU Bootloader Reference Manual:

  • bootloader_config.h
  • target_config.h
  • peripherals_pinmux.h
  • memory_map_<device>.c
  • hardware_init_<device>.c
  • peripherals_<device>.c
  • clock_config_<device>.c

 

Additionally, if you are using FlexCAN, you may need to define a "const flexcan_timing_config_t bit_rate_table[]" in source/bootloader/src/flexcan_peripheral_interface.c

Outcomes