0
votes

I am looking into using the NXP LPC4330 microcontroller in a future design and one of the features we need is the ability to update flash in the field using a bootloader. In the past I have done this using the NXP IAP commands, but since the 4330 uses SPIFI flash, IAP is not available.

From what I have gathered, it seems that my bootloader application will need to be executing from RAM and then I can write to flash using the SPIFI library from NXP. My question is this:

Using IAR Embedded Workbench, how can I create a program that will start from flash and then start running via RAM so I can write to the SPIFI chip? I have looked at the example below, but it is unclear how to port it over to the LPC4330. I believe I have the code copied into RAM in the startup code, but not sure how to copy the interrupt vector table to RAM or how to start executing from RAM. https://www.iar.com/support/tech-notes/general/execute-in-ram-after-copying-from-flashrom-v5.20-and-later/

2

2 Answers

0
votes

what I often do is write the main program and link it for ram only, make a complete binary. Then I write a thin shell program for flash whose entire job is to copy and jump. usually a few lines of assembly plus the contents of the binary file for the main program (I tend to write an adhoc host util to turn the main program into .word or an array of words if using C to link in with the flash program.

I have no use for IDEs so cant help you with your specific tools, I assume they have command line tools that the ide calls and you can use those and a makefile.

0
votes

I figured out how this is done. Using the link in the question to get a good idea of the general process.

This is what the startup file should look like. There is an interrupt vector table in flash, with all interrupt vectors pointing to a dummy handler. Then later on there is an interrupt vector table stored in RAM which is used.

;Interrupt vector table in flash, will never be used since VTOR 
;(interrupt vector table)will be mapped to RAM on startup
        MODULE  ?cstartup

        ;; Forward declaration of sections.
        SECTION CSTACK:DATA:NOROOT(3)

        SECTION .intvec:CODE:NOROOT(2)

        EXTERN  __iar_program_start 
        EXTERN  SystemInit        
        PUBLIC  __vector_table_RAM
        PUBLIC  __vector_table_0x1c
        PUBLIC  __Vectors
        PUBLIC  __Vectors_End
        PUBLIC  __Vectors_Size

        DATA

__vector_table
        DCD     sfe(CSTACK)
        DCD     Reset_Handler
        DCD     NMI_Handler
        DCD     HardFault_Handler
        DCD     MemManage_Handler
        DCD     BusFault_Handler
        DCD     UsageFault_Handler
__vector_table_0x1c
        DCD     0
        DCD     0
        DCD     0
        DCD     0
        DCD     SVC_Handler
        DCD     DebugMon_Handler
        DCD     0
        DCD     PendSV_Handler
        DCD     SysTick_Handler

        ; External Interrupts
        DCD     Dummy_Handler_ROM               ; 16 D/A Converter
        DCD     Dummy_Handler_ROM               ; 17 CortexM0 (LPC43XX ONLY) 
        DCD     Dummy_Handler_ROM               ; 18 General Purpose DMA
        DCD     0                               ; 19 Reserved
        DCD     Dummy_Handler_ROM               ; 20 ORed flash bank A, flash bank B, EEPROM interrupts
        DCD     Dummy_Handler_ROM               ; 21 Ethernet
        DCD     Dummy_Handler_ROM               ; 22 SD/MMC
        DCD     Dummy_Handler_ROM               ; 23 LCD
        DCD     Dummy_Handler_ROM               ; 24 USB0
        DCD     Dummy_Handler_ROM               ; 25 USB1
        DCD     Dummy_Handler_ROM               ; 26 State Configurable Timer
        DCD     Dummy_Handler_ROM               ; 27 Repetitive Interrupt Timer
        DCD     Dummy_Handler_ROM               ; 28 Timer0
        DCD     Dummy_Handler_ROM               ; 29 Timer1
        DCD     Dummy_Handler_ROM               ; 30 Timer2
        DCD     Dummy_Handler_ROM               ; 31 Timer3
        DCD     Dummy_Handler_ROM               ; 32 Motor Control PWM
        DCD     Dummy_Handler_ROM               ; 33 A/D Converter 0
        DCD     Dummy_Handler_ROM               ; 34 I2C0
        DCD     Dummy_Handler_ROM               ; 35 I2C1
        DCD     Dummy_Handler_ROM               ; 36 SPI (LPC43XX ONLY)
        DCD     Dummy_Handler_ROM               ; 37 A/D Converter 1
        DCD     Dummy_Handler_ROM               ; 38 SSP0
        DCD     Dummy_Handler_ROM               ; 39 SSP1
        DCD     Dummy_Handler_ROM               ; 40 UART0
        DCD     Dummy_Handler_ROM               ; 41 UART1
        DCD     Dummy_Handler_ROM               ; 42 UART2
        DCD     Dummy_Handler_ROM               ; 43 UART3
        DCD     Dummy_Handler_ROM               ; 44 I2S0
        DCD     Dummy_Handler_ROM               ; 45 I2S1
        DCD     Dummy_Handler_ROM               ; 46 SPI Flash Interface
        DCD     Dummy_Handler_ROM               ; 47 SGPIO (LPC43XX ONLY)
        DCD     Dummy_Handler_ROM               ; 48 GPIO0
        DCD     Dummy_Handler_ROM               ; 49 GPIO1
        DCD     Dummy_Handler_ROM               ; 50 GPIO2
        DCD     Dummy_Handler_ROM               ; 51 GPIO3
        DCD     Dummy_Handler_ROM               ; 52 GPIO4
        DCD     Dummy_Handler_ROM               ; 53 GPIO5
        DCD     Dummy_Handler_ROM               ; 54 GPIO6
        DCD     Dummy_Handler_ROM               ; 55 GPIO7
        DCD     Dummy_Handler_ROM               ; 56 GINT0
        DCD     Dummy_Handler_ROM               ; 57 GINT1
        DCD     Dummy_Handler_ROM               ; 58 Event Router
        DCD     Dummy_Handler_ROM               ; 59 C_CAN1
        DCD     0
        DCD     Dummy_Handler_ROM               ; 61 ADCHS combined interrupt
        DCD     Dummy_Handler_ROM               ; 62 ATIMER
        DCD     Dummy_Handler_ROM               ; 63 RTC
        DCD     0
        DCD     Dummy_Handler_ROM               ; 65 WDT
        DCD     Dummy_Handler_ROM               ; 66 M0SUB TXEVT
        DCD     Dummy_Handler_ROM               ; 67 C_CAN0
        DCD     Dummy_Handler_ROM               ; 68 QEI




;Interrupt vector table which will be placed in RAM
        SECTION .vectors_RAM:CODE:ROOT(2)

        EXTERN  __iar_program_start 
        EXTERN  SystemInit        
        PUBLIC  __vector_table
        PUBLIC  __vector_table_0x1c
        PUBLIC  __Vectors
        PUBLIC  __Vectors_End
        PUBLIC  __Vectors_Size

        DATA
__vector_table_RAM
        DCD     sfe(CSTACK)
        DCD     Reset_Handler
        DCD     NMI_Handler
        DCD     HardFault_Handler
        DCD     MemManage_Handler
        DCD     BusFault_Handler
        DCD     UsageFault_Handler
        DCD     0
        DCD     0
        DCD     0
        DCD     0
        DCD     SVC_Handler
        DCD     DebugMon_Handler
        DCD     0
        DCD     PendSV_Handler
        DCD     SysTick_Handler

        ; External Interrupts
        DCD     DAC_IRQHandler              ; 16 D/A Converter
        DCD     M0APP_IRQHandler            ; 17 CortexM0 (LPC43XX ONLY) 
        DCD     DMA_IRQHandler              ; 18 General Purpose DMA
        DCD     0                           ; 19 Reserved
        DCD     FLASH_EEPROM_IRQHandler     ; 20 ORed flash bank A, flash bank B, EEPROM interrupts
        DCD     ETH_IRQHandler              ; 21 Ethernet
        DCD     SDIO_IRQHandler             ; 22 SD/MMC
        DCD     LCD_IRQHandler              ; 23 LCD
        DCD     USB0_IRQHandler             ; 24 USB0
        DCD     USB1_IRQHandler             ; 25 USB1
        DCD     SCT_IRQHandler              ; 26 State Configurable Timer
        DCD     RIT_IRQHandler              ; 27 Repetitive Interrupt Timer
        DCD     TIMER0_IRQHandler           ; 28 Timer0
        DCD     TIMER1_IRQHandler           ; 29 Timer1
        DCD     TIMER2_IRQHandler           ; 30 Timer2
        DCD     TIMER3_IRQHandler           ; 31 Timer3
        DCD     MCPWM_IRQHandler            ; 32 Motor Control PWM
        DCD     ADC0_IRQHandler             ; 33 A/D Converter 0
        DCD     I2C0_IRQHandler             ; 34 I2C0
        DCD     I2C1_IRQHandler             ; 35 I2C1
        DCD     SPI_IRQHandler              ; 36 SPI (LPC43XX ONLY)
        DCD     ADC1_IRQHandler             ; 37 A/D Converter 1
        DCD     SSP0_IRQHandler             ; 38 SSP0
        DCD     SSP1_IRQHandler             ; 39 SSP1
        DCD     UART0_IRQHandler            ; 40 UART0
        DCD     UART1_IRQHandler            ; 41 UART1
        DCD     UART2_IRQHandler            ; 42 UART2
        DCD     UART3_IRQHandler            ; 43 UART3
        DCD     I2S0_IRQHandler             ; 44 I2S0
        DCD     I2S1_IRQHandler             ; 45 I2S1
        DCD     SPIFI_IRQHandler            ; 46 SPI Flash Interface
        DCD     SGPIO_IRQHandler            ; 47 SGPIO (LPC43XX ONLY)
        DCD     GPIO0_IRQHandler            ; 48 GPIO0
        DCD     GPIO1_IRQHandler            ; 49 GPIO1
        DCD     GPIO2_IRQHandler            ; 50 GPIO2
        DCD     GPIO3_IRQHandler            ; 51 GPIO3
        DCD     GPIO4_IRQHandler            ; 52 GPIO4
        DCD     GPIO5_IRQHandler            ; 53 GPIO5
        DCD     GPIO6_IRQHandler            ; 54 GPIO6
        DCD     GPIO7_IRQHandler            ; 55 GPIO7
        DCD     GINT0_IRQHandler            ; 56 GINT0
        DCD     GINT1_IRQHandler            ; 57 GINT1
        DCD     EVRT_IRQHandler             ; 58 Event Router
        DCD     CAN1_IRQHandler             ; 59 C_CAN1
        DCD     0
        DCD     ADCHS_IRQHandler            ; 61 ADCHS combined interrupt
        DCD     ATIMER_IRQHandler           ; 62 ATIMER
        DCD     RTC_IRQHandler              ; 63 RTC
        DCD     0
        DCD     WDT_IRQHandler              ; 65 WDT
        DCD     M0SUB_IRQHandler            ; 66 M0SUB TXEVT
        DCD     CAN0_IRQHandler             ; 67 C_CAN0
        DCD     QEI_IRQHandler              ; 68 QEI
__Vectors_End

__Vectors       EQU   __vector_table
__Vectors_Size  EQU   __Vectors_End - __Vectors

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Default interrupt handlers.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        THUMB

        PUBWEAK Reset_Handler
        SECTION .text:CODE:REORDER:NOROOT(2)
Reset_Handler
        LDR     R0, =SystemInit
        BLX     R0
        LDR     R0, =__iar_program_start
        BX      R0

        PUBWEAK NMI_Handler
        PUBWEAK HardFault_Handler
        PUBWEAK MemManage_Handler
        PUBWEAK BusFault_Handler
        PUBWEAK UsageFault_Handler
        PUBWEAK SVC_Handler
        PUBWEAK DebugMon_Handler
        PUBWEAK PendSV_Handler
        PUBWEAK SysTick_Handler
        PUBWEAK DAC_IRQHandler
        PUBWEAK M0APP_IRQHandler
        PUBWEAK DMA_IRQHandler
        PUBWEAK FLASH_EEPROM_IRQHandler
        PUBWEAK ETH_IRQHandler
        PUBWEAK SDIO_IRQHandler
        PUBWEAK LCD_IRQHandler
        PUBWEAK USB0_IRQHandler
        PUBWEAK USB1_IRQHandler
        PUBWEAK SCT_IRQHandler
        PUBWEAK RIT_IRQHandler
        PUBWEAK TIMER0_IRQHandler
        PUBWEAK TIMER1_IRQHandler
        PUBWEAK TIMER2_IRQHandler
        PUBWEAK TIMER3_IRQHandler
        PUBWEAK MCPWM_IRQHandler
        PUBWEAK ADC0_IRQHandler
        PUBWEAK I2C0_IRQHandler
        PUBWEAK I2C1_IRQHandler
        PUBWEAK SPI_IRQHandler
        PUBWEAK ADC1_IRQHandler
        PUBWEAK SSP0_IRQHandler
        PUBWEAK SSP1_IRQHandler
        PUBWEAK UART0_IRQHandler
        PUBWEAK UART1_IRQHandler
        PUBWEAK UART2_IRQHandler
        PUBWEAK UART3_IRQHandler
        PUBWEAK I2S0_IRQHandler
        PUBWEAK I2S1_IRQHandler
        PUBWEAK SPIFI_IRQHandler
        PUBWEAK SGPIO_IRQHandler
        PUBWEAK GPIO0_IRQHandler
        PUBWEAK GPIO1_IRQHandler
        PUBWEAK GPIO2_IRQHandler
        PUBWEAK GPIO3_IRQHandler
        PUBWEAK GPIO4_IRQHandler
        PUBWEAK GPIO5_IRQHandler
        PUBWEAK GPIO6_IRQHandler
        PUBWEAK GPIO7_IRQHandler
        PUBWEAK GINT0_IRQHandler
        PUBWEAK GINT1_IRQHandler
        PUBWEAK EVRT_IRQHandler
        PUBWEAK CAN1_IRQHandler
        PUBWEAK ADCHS_IRQHandler
        PUBWEAK ATIMER_IRQHandler
        PUBWEAK RTC_IRQHandler
        PUBWEAK WDT_IRQHandler
        PUBWEAK M0SUB_IRQHandler
        PUBWEAK CAN0_IRQHandler
        PUBWEAK QEI_IRQHandler
        SECTION .text:CODE:REORDER:NOROOT(1)
NMI_Handler
        B NMI_Handler
SVC_Handler
        B SVC_Handler
DebugMon_Handler
        B DebugMon_Handler
PendSV_Handler
        B PendSV_Handler
SysTick_Handler
        B SysTick_Handler
HardFault_Handler
        B HardFault_Handler
MemManage_Handler
        B MemManage_Handler
BusFault_Handler
        B BusFault_Handler
UsageFault_Handler
DAC_IRQHandler
M0APP_IRQHandler
DMA_IRQHandler 
FLASH_EEPROM_IRQHandler
ETH_IRQHandler
SDIO_IRQHandler
LCD_IRQHandler
USB0_IRQHandler
USB1_IRQHandler
SCT_IRQHandler
RIT_IRQHandler
TIMER0_IRQHandler
TIMER1_IRQHandler
TIMER2_IRQHandler
TIMER3_IRQHandler
MCPWM_IRQHandler
ADC0_IRQHandler
I2C0_IRQHandler
I2C1_IRQHandler
SPI_IRQHandler
ADC1_IRQHandler
SSP0_IRQHandler
SSP1_IRQHandler
UART0_IRQHandler
UART1_IRQHandler
UART2_IRQHandler
UART3_IRQHandler
I2S0_IRQHandler
I2S1_IRQHandler
SPIFI_IRQHandler
SGPIO_IRQHandler
GPIO0_IRQHandler
GPIO1_IRQHandler
GPIO2_IRQHandler
GPIO3_IRQHandler
GPIO4_IRQHandler
GPIO5_IRQHandler
GPIO6_IRQHandler
GPIO7_IRQHandler
GINT0_IRQHandler
GINT1_IRQHandler
EVRT_IRQHandler
CAN1_IRQHandler
ADCHS_IRQHandler
ATIMER_IRQHandler
RTC_IRQHandler
WDT_IRQHandler
CAN0_IRQHandler
M0SUB_IRQHandler
QEI_IRQHandler
Default_IRQHandler
        B Default_IRQHandler

/* CRP Section - not needed for flashless devices */

;;;        SECTION .crp:CODE:ROOT(2)
;;;        DATA
/* Code Read Protection
NO_ISP  0x4E697370 -  Prevents sampling of pin PIO0_1 for entering ISP mode
CRP1    0x12345678 - Write to RAM command cannot access RAM below 0x10000300.
                   - Copy RAM to flash command can not write to Sector 0.
                   - Erase command can erase Sector 0 only when all sectors
                     are selected for erase.
                   - Compare command is disabled.
                   - Read Memory command is disabled.
CRP2    0x87654321 - Read Memory is disabled.
                   - Write to RAM is disabled.
                   - "Go" command is disabled.
                   - Copy RAM to flash is disabled.
                   - Compare is disabled.
CRP3    0x43218765 - Access to chip via the SWD pins is disabled. ISP entry
                     by pulling PIO0_1 LOW is disabled if a valid user code is
                     present in flash sector 0.
Caution: If CRP3 is selected, no future factory testing can be
performed on the device.
*/
;;;     DCD 0xFFFFFFFF
;;;

; --------------------
; Dummy handler placed in ROM

Dummy_Handler_ROM
                b       Dummy_Handler_ROM

        END

Then the linker file (.icf) needs to be edited to put all of the readonly items in ram (readwrite section) as shown below. The important line is "initialize by copy"

/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x14000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x14000140;
define symbol __ICFEDIT_region_ROM_end__   = 0x140FFFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x10000140;
define symbol __ICFEDIT_region_RAM_end__   = 0x10007FFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x800;
define symbol __ICFEDIT_size_heap__   = 0x200;
/**** End of ICF editor section. ###ICF###*/

define symbol RAM_vectors_start = 0x10000000;

define memory mem with size = 4G;
define region ROM_region   = mem:[from __ICFEDIT_region_ROM_start__   to __ICFEDIT_region_ROM_end__];
define region RAM_region   = mem:[from __ICFEDIT_region_RAM_start__   to __ICFEDIT_region_RAM_end__];

define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };

initialize by copy { readonly, readwrite };
do not initialize  { section .noinit };

place at address mem:__ICFEDIT_intvec_start__ { section .intvec };

place at address mem:RAM_vectors_start { section .vectors_RAM };

place in ROM_region     { readonly };
place in RAM_region     { readwrite,
                          block CSTACK, block HEAP };

After that, the only thing left to do is remap the interrupt vector table to RAM from ROM. This should be the first thing your application does, before any interrupts are enabled. The code should look like this:

VTOR = (unsigned int) 0x10000000;