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;