We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hello,
I'm using a lpc1766 and made a simple program to toggle a led from a timer interrupt. At first the interrupt vectors were in flash (see startup code below) and this worked just fine. So I assume that my timer initialisation and interrupt handling are ok.
Then I made a initialisation routine to copy the vector table to a ram table and then remap the vector table using the Vtor register.
When running the program it seems that the program constantly resets and thus something went wrong with the remapping.
Does anyone have an idea about what's going wrong?!
;/***********************************************************************/ ; INTERRUPT VECTOR TABLE ; Default interrupt vectors are mapped to the resetvector. Software sets ; the vector to the actual interrupt handler for that peripheral. ; ;/***********************************************************************/ AREA RESET, DATA, READONLY EXPORT __Vectors IMPORT timer_interrupt __Vectors DCD __initial_sp ; Top of Stack DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD MemManage_Handler ; MPU Fault Handler DCD BusFault_Handler ; Bus Fault Handler DCD UsageFault_Handler ; Usage Fault Handler DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD SVC_Handler ; SVCall Handler DCD DebugMon_Handler ; Debug Monitor Handler DCD 0 ; Reserved DCD PendSV_Handler ; PendSV Handler DCD SysTick_Handler ; SysTick Handler ; External Interrupts DCD Reset_Handler ; 16: Watchdog Timer DCD Reset_Handler ; 17: Timer0 DCD timer_interrupt ; 18: Timer1 DCD Reset_Handler ; 19: Timer2 DCD Reset_Handler ; 20: Timer3 DCD Reset_Handler ; 21: UART0 DCD Reset_Handler ; 22: UART1 DCD Reset_Handler ; 23: UART2 DCD Reset_Handler ; 24: UART3 DCD Reset_Handler ; 25: PWM1 DCD Reset_Handler ; 26: I2C0 DCD Reset_Handler ; 27: I2C1 DCD Reset_Handler ; 28: I2C2 DCD Reset_Handler ; 29: SPI DCD Reset_Handler ; 30: SSP0 DCD Reset_Handler ; 31: SSP1 DCD Reset_Handler ; 32: PLL0 Lock (Main PLL) DCD Reset_Handler ; 33: Real Time Clock DCD Reset_Handler ; 34: External Interrupt 0 DCD Reset_Handler ; 35: External Interrupt 1 DCD Reset_Handler ; 36: External Interrupt 2 DCD Reset_Handler ; 37: External Interrupt 3 DCD Reset_Handler ; 38: A/D Converter DCD Reset_Handler ; 39: Brown-Out Detect DCD Reset_Handler ; 40: USB DCD Reset_Handler ; 41: CAN DCD Reset_Handler ; 42: General Purpose DMA DCD Reset_Handler ; 43: I2S DCD Reset_Handler ; 44: Ethernet DCD Reset_Handler ; 45: Repetitive Interrupt Timer DCD Reset_Handler ; 46: Motor Control PWM DCD Reset_Handler ; 47: Quadrature Encoder Interface DCD Reset_Handler ; 48: PLL1 Lock (USB PLL) IF :LNOT::DEF:NO_CRP AREA |.ARM.__at_0x02FC|, CODE, READONLY CRP_Key DCD 0xFFFFFFFF ENDIF
The vector table remap routine:
volatile uint32 int_vector_table[VECTOR_TABLE_LEN] __attribute__((at(0x10000000))); /*************************** FUNCTION ************************************/ void init_interrupt_controller(void) /*************************** INFO **************************************** ** ** DESCRIPTION : Initialize the interrupt controller and the interrupt ** vector table. ** ** INPUT : ** ** OUTPUT : ** ** RETURN : **************************************************************************/ { uint8 int_number; volatile const uint32 *org_table = 0x00000000; nvic->cer[0] = 0xFFFFFFFF; nvic->cer[1] = 0x00000007; for(int_number = 0; int_number < VECTOR_TABLE_LEN; int_number++) int_vector_table[int_number] = org_table[int_number]; for(int_number = 0; int_number < MAX_INT_VECTORS; int_number++) { set_interrupt_prioriy(int_number, 15L); } scb->vtor = (uint32)(&int_vector_table) | (0x00000001 << 29); }
/******************************************************************************* * Function Name : NVIC_SetVectorTable * Description : Sets the vector table location and Offset. * Input : - NVIC_VectTab: specifies if the vector table is in RAM or * FLASH memory. * This parameter can be one of the following values: * - NVIC_VectTab_RAM * - NVIC_VectTab_FLASH * - Offset: Vector Table base offset field. * This value must be a multiple of 0x100. * Output : None * Return : None *******************************************************************************/ void NVIC_SetVectorTable(DWORD NVIC_VectTab, DWORD Offset) { NVIC_VECT_TABLE = NVIC_VectTab | (Offset & 0x1FFFFF80); }
I don't see how your solution differs from mine!
But I got it working now. I moved the interrupt vector table in ram from address 0x10000000 to 0x2007c0000.
volatile uint32 int_vector_table[VECTOR_TABLE_LEN] __attribute__((at(0x2007C000)));
Why doenst it work when the table is at 0x1000000?
Hello Sander Wiggers,
It is posible to map the vector table to 0x10000000.
You are using the following code to remap the vector table:
scb->vtor = (uint32)(&int_vector_table) | (0x00000001 << 29);
This results in the address 0x30000000 where the controller expects the vector table. To remap the vector table following code is sufficient:
scb->vtor = (uint32)(&int_vector_table);
The SRAM area of a Cortex-M3 starts normally at 0x20000000. This means Bit[29] is a 1. This is the reason why TBLBASE bit (Bit[29]) in VTOR register stands for 1= SRAM. But LPC17xx SRAM starts at 0x1000000. Setting additionally TBLBASE bit (Bit[29]) results in a wrong vector table remap address.
Please see also Blinky project in folder .\Keil\ARM\Boards\Keil\MCB1700\Blinky Target LPC1768 RAM. File RAM.ini is used to remap the vector table.
Best Regards, Martin Guenther
Indeed, this seems to work. Thanks for your answer.
Sander