Where to add code for ROM vector table copy to RAM?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Where to add code for ROM vector table copy to RAM?

16,800 Views
Cdn_aye
Senior Contributor I

Hi

I rebuilt the mqx 3.8.1 for the k40, with the user_config.h with MQX_ROM_VECTORS   0

Then I changed the intflash.lcf to the code below, as per the appnotes and rebuilt the bsp.

But in what module do I add the code to copy the ROM vector table to RAM, is that in mqx_main.c in the bsp sources directory, or do I do that in my code? I am assuming that the table should be setup before the NVIC is set up? Which would put that into one of the bsp init modules, but which one?

Should I delete the first -->4th line because it is in the MEMORY {} array (this was dropped in from the appnote)?

Shouldn't the VectorRam start at 0x1FFF_8000 for the k40x256, the appnote uses 0x1FFF_0400

I am new to the lcf file and really do not have a good understanding of what is essential and what is not. Any help would be appreciated.

Thank you

Robert

/////////////////////////////////////////////////////////////////////////////////////////////

   vectorrom   (RX): ORIGIN = 0x00010000, LENGTH = 0x00000400

   cfmprotrom  (RX): ORIGIN = 0x00010400, LENGTH = 0x00000020

   rom         (RX): ORIGIN = 0x00010420, LENGTH = 0x0002FBE0  # Code + Const data  

   ram         (RW): ORIGIN = 0x1FFF8000, LENGTH = 0x00010000  # SRAM - RW data

   # kernel space starts after RAM variables (Location of MQX Kernel data + MQX heap)

   end_of_kd   (RW): ORIGIN = 0x20007FF0, LENGTH = 0x00000000

  

   # Boot stack reused by MQX Kernel data

   bstack      (RW): ORIGIN = 0x20007A00, LENGTH = 0x00000200  # Boot stack

   end_bstack  (RW): ORIGIN = 0x20007BFF, LENGTH = 0x00000000

}

KEEP_SECTION { .vectortable }

MEMORY {

   interrupts (RX) : ORIGIN = 0x00010000, LENGTH = 0x00000400

   vectorram (RWX) : ORIGIN = 0x1FFF0000, LENGTH = 0x00000400

   data (RW) : ORIGIN = 0x1FFF0400, LENGTH = 0x0002FC00

}

.interrupts :

{

___VECTOR_ROM = .;

* (.vectortable)

. = ALIGN (0x4);

} > interrupts

.vectorram : {

___VECTOR_RAM = .;

} > vectorram

Labels (2)
Tags (2)
17 Replies

2,404 Views
Cdn_aye
Senior Contributor I

Hi David

I added the code, thank you. I have the bootloader flashing the file from the USB and according to the bootloader there are no errors in the erase or flash.

But the next problem is, I am still reading 0xFFFF_FFFF for the sp, and pc, from

void _bsp_platform_init(void)

{

   uint_32 n;

  /* Point the VTOR to the new copy of the vector table */

  SCB_VTOR = (uint_32)___VECTOR_RAM;

MEMORY {

  interrupts  (RX) : ORIGIN = 0x00000000, LENGTH = 0x000001E0

  code        (RX) : ORIGIN = 0x00000410, LENGTH = 0x0003FBF0

  data14000000 (RW) : ORIGIN = 0x14000000, LENGTH = 0x00001000

  data        (RW) : ORIGIN = 0x1FFF8000, LENGTH = 0x00010000

  cfmprotrom  (RX) : ORIGIN = 0x00000400, LENGTH = 0x00000400

}

This is the app lcf file

MEMORY

{

   vectorrom   (RX): ORIGIN = 0x00001000, LENGTH = 0x00000400

#   cfmprotrom  (RX): ORIGIN = 0x00000400, LENGTH = 0x00000020

   rom         (RX): ORIGIN = 0x00001420, LENGTH = 0x0002FBE0  # Code + Const data  

   ram         (RW): ORIGIN = 0x1FFF8000, LENGTH = 0x00010000  # SRAM - RW data

   # kernel space starts after RAM variables (Location of MQX Kernel data + MQX heap)

   end_of_kd   (RW): ORIGIN = 0x20007FF0, LENGTH = 0x00000000

  

   # Boot stack reused by MQX Kernel data

   bstack      (RW): ORIGIN = 0x20007A00, LENGTH = 0x00000200  # Boot stack

   end_bstack  (RW): ORIGIN = 0x20007BFF, LENGTH = 0x00000000

}

KEEP_SECTION { .vectors_rom, .vectors_ram, .cfmconfig }

SECTIONS

{

   __INTERNAL_SRAM_BASE  = 0x1FFF8000;

   __INTERNAL_SRAM_SIZE  = 0x00010000;

   __INTERNAL_FLASH_BASE = 0x00000000;

   __INTERNAL_FLASH_SIZE = 0x00040000;

   __INTERNAL_FLEXNVM_BASE = 0x10000000;

   __INTERNAL_FLEXNVM_SIZE = 0x00040000;

   __INTERNAL_FLEXRAM_BASE = 0x14000000;

   __INTERNAL_FLEXRAM_SIZE = 0x00004000;

  

   __EXTERNAL_MRAM_BASE  = 0x70000000;

   __EXTERNAL_MRAM_SIZE  = 0x00080000;

   __EXTERNAL_MRAM_ROM_BASE = 0x70000000;

   __EXTERNAL_MRAM_ROM_SIZE = 0x00000000;

   __EXTERNAL_MRAM_RAM_BASE = 0x70000000;

   __EXTERNAL_MRAM_RAM_SIZE = 0x00080000;

   __EXTERNAL_LCD_BASE = 0x60000000;

   __EXTERNAL_LCD_SIZE = 0x1FFFF;

   __EXTERNAL_LCD_DC_BASE = 0x60010000;

   # MQX link time configurations

   __DEFAULT_PROCESSOR_NUMBER = 1;

   __DEFAULT_INTERRUPT_STACK_SIZE = 1024;

   __KERNEL_DATA_VERIFY_ENABLE = 0;    # Test SDRAM read/write

   # Flashx configurations

   __FLASHX_SECT_SIZE = 0x800;

    .vectors :

    {

        __VECTOR_TABLE_ROM_START = .;        # Runtime vector table in sram

        *(.vectors_rom)

        . = ALIGN (0x4);

    } > vectorrom

#    .cfmprotect :

#    {

#        *(.cfmconfig)

#        . = ALIGN (0x4);

#    } > cfmprotrom

    .main_application :

    {

        *(KERNEL)

        *(S_BOOT)

        *(IPSUM)

        *(.text)

        *(.init)

        *(.fini)

        *(.eini)

        *(.ctors)

        *(.dtors)

        . = ALIGN(0x4);

        *(.rodata)

        . = ALIGN(0x4);

        *(.rdata)

        . = ALIGN(0x4);

        *(.exception)

        . = ALIGN(0x4);

        __exception_table_start__ = .;

        EXCEPTION

        __exception_table_end__ = .;

        __sinit__ = .;

        STATICINIT

        . = ALIGN(0x4);

        __COPY_OF_DATA = .;

    } > rom

    .main_application_data : AT(__COPY_OF_DATA)

    {

        . = ALIGN(128);

        __VECTOR_TABLE_RAM_START = .;        # Runtime vector table in sram

        *(.vectors_ram)

        . = ALIGN(512);

        __BDT_BASE = .;

        *(.usb_bdt)

        __BDT_END = .;

        __START_DATA = .;

        *(.data)

        __END_DATA = .;

        . = ALIGN(0x4);

        __START_SDATA = .;

        *(.sdata)

        __END_SDATA = .;

        . = ALIGN(0x4);

        __SDA_BASE  = .;

        __SDA_BASE_ = __SDA_BASE;

        . = ALIGN(16);

    } > ram

    .main_application_bss :

    {

        . = ALIGN(0x10);

        __START_SBSS = .;

        *(.sbss)

        *(SCOMMON)

        __END_SBSS = .;

        __START_BSS = .;

        *(.bss)

        *(COMMON)

        __END_BSS = .;

        . = ALIGN(16);

    } >> ram

    .kernel_data : #AT(ADDR(.main_application_bss) + SIZEOF(.main_application_bss))

    {

        __KERNEL_DATA_START = ALIGN(0x10);

    }

    .end_of_kernel_data :

    {

        __KERNEL_DATA_END = .;

    } > end_of_kd

    .boot_stack :

    {

        _stack_end = .;

    } > bstack

  

    .end_of_boot_stack :

    {

        _stack_addr  = .;

        __SP_INIT    = .;

        __BOOT_STACK_ADDRESS = .;

    } > end_bstack

    # Locate the ROM copy table into ROM after the initialized data

    _romp_at = __COPY_OF_DATA + SIZEOF(.main_application_data);

    .romp : AT (_romp_at)

    {

        __S_romp = _romp_at;

        WRITEW(__COPY_OF_DATA);                    #ROM start address

        WRITEW(ADDR(.main_application_data));      #RAM start address

        WRITEW(SIZEOF(.main_application_data));    #size

        WRITEW(0);

        WRITEW(0);

        WRITEW(0);

    }

    _flashx_start = __COPY_OF_DATA + SIZEOF(.main_application_data) + SIZEOF(.romp);

    # flashx working area spans across the whole rest of Flash memory

    __FLASHX_START_ADDR = ((_flashx_start + __FLASHX_SECT_SIZE - 1) / __FLASHX_SECT_SIZE) * __FLASHX_SECT_SIZE;

    __FLASHX_END_ADDR = __INTERNAL_FLASH_BASE + __INTERNAL_FLASH_SIZE;

}

/* EOF */

The app is from 0001_0000 and on, with mqx having the vector table set to RAM, that appears to be correct from the xmap file. But I think the boot loader needs to find the __VECTOR_RAM address and get the PC, and SP from there... is that correct? What I don't see being done is the build against that location.

Even through I commented out the cfmprotrom, it is still in the xmap memory map.

Regards

Robert

0 Kudos
Reply

2,404 Views
DavidS
NXP Employee
NXP Employee

Hi Robert, Glad boot loader is working. The boot loader can get the stack pointer and PC from the application vector table at 0x10000 and 0x10004 respectively. Once boot loader jumps to the application, the application will set the vector table (VTOR) according to the MQX_VECTOR_TABLE. Regards, David

0 Kudos
Reply

2,404 Views
Cdn_aye
Senior Contributor I

Hi David

The boot ldr is working but I can not jump to the program start. I always load ffff for the stack and pc. I this was why I asked about how to set the vector table linkage in the boot loader. I am see the btldr getting its values from an 2 element array for the new stack and pc ptrs. But I don't see the this array initialized.

Regards

Robert

0 Kudos
Reply

2,404 Views
DavidS
NXP Employee
NXP Employee

Hi Robert,

Sorry for delay...weekend and vacation day Monday.

Please review your linker file.  Above you have 0x1000 for vectrrom.

If you look at my linker script above and copied here:

For the MQX test application I only changed the following in the linker file used to place app @0x10000:

MEMORY

{

   vectorrom   (RX): ORIGIN = 0x00010000, LENGTH = 0x00000400

   cfmprotrom  (R): ORIGIN = 0x00010400, LENGTH = 0x00000020

   rom         (RX): ORIGIN = 0x00010420, LENGTH = 0x0007FBE0  # Code + Const data

For the MQX test application I only changed the following in the linker file used:

My vectorrom is 0x0001_0000....likewise the cfmprotrom and rom need updating.

Before you ask, cfmprotrom is not needed for the MQX application when a bootloader is present.  But instead of removing it, it can be left as one less step to take.

Regards,

David

PS

I've run my MQX application with MQX_ROM_VECTORS 0 (RAM) and 1 (ROM) successfully with the bootloader.

0 Kudos
Reply

2,404 Views
Cdn_aye
Senior Contributor I

Hi David

The lcf file was wrong as you pointed out... thank you. I thought I had used 0001_0000 but had used 0000_1000. Weariness and persistence do not always produce good results.

Now I am getting an unexpected ISR trap. Do you know any way to assign unique ISRs to all the unused ISR's. I can't figure out which one is causing the trap. The system appears to start and that continually traps to the unexpected ISR. Manually entering all these would be a painful process.

Thanks again

Robert

0 Kudos
Reply

2,404 Views
PetrL
NXP Employee
NXP Employee

Hi,

if you need to find out active interrupt number you can check IPSR or ICSR register.

ARM Information Center: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/CHDBIBGJ.html

PetrL

0 Kudos
Reply

2,404 Views
BryGuyH
Contributor IV

In theory... in practice however that does not yield particularly good results because nearly always the unexpected isr gets thrown by the hardfault interrupt.

Because of the topic I am sure the processor is hardfaulting due to any number of reasons (bad alignment, trying to write to the watchdog at the wrong time, a write to a module who's clock is currently off, etc).

2,404 Views
PetrL
NXP Employee
NXP Employee

Right, IPSR helps in case that interrupt source is from peripheral.

In case the unexpected ISR is caused by hardfault the situation is indeed more complicated. It can be found out if the error was busfault/usage fault or mem. fault.. but it also do not help a lot.

Then there is no other way than find the exact place of failure..

@Robert- could you find out exact what place in code causes your error?

2,404 Views
Cdn_aye
Senior Contributor I

That is the problem... I really can't tell where the interrupt is coming from. I have tried to do a return to find out why, but I just trap back and I just get this unassigned ISR trap.

That is why I wanted to have MQX generate unique ISR entry points for all the  possible ISR's. Processor Expert used to do this and someone once mentioned that MQX could also do this, but I can't see how to do so. I know I can manually create 100+ entry IRQ routines and fill in the vector table, but that is a brutal solution. Failing that I need a way to trace the execution and I don't have that either.

If anyone knows how to do the above please post as I know it is of interest to others as well. Thanks for the suggestions.

Robert

0 Kudos
Reply

2,404 Views
BryGuyH
Contributor IV

In general just changing the #define should be enough (but yes the linker file does need to match your chip - for that we need the part number). To answer your questions though:

Copying the vector table:

  • The compiler/linker does the copy for you. (i.e. no need to do it explicity - that is what the linker configuration file is for. the resulting assembly code will have the loads required)
  • The VTOR register is set by _int_set_vector_table in init_bsp.c

Memory base address:

0x1FFF8000 would be the base address for a 64KB part. See section 3.5.3.2 of the reference manual.To figure out the proper base address we need to know the full part number.

Ram Vector table location

For a 128kB part you could put the ram table at 0x1FFF0400 based on alignment requirements if you weren't going to put it at 0x1FFF0000. The docs for this are all over the place:

a) ARM documentation for the VTOR register ARM Information Center

b) You need to get the vector count from the K40 sub family reference manual and do the math from the arm reference (the K20 and K60 align to 0x400 - half flash page - so I would assume the K40 would as well, but no hurt in verifying)

2,404 Views
Cdn_aye
Senior Contributor I

Bryan, thank you for replying.

We had to use the bsp for the k40dx256 because there is no specific bsp for our chip. We are using the k20dx256VLL10, 64kb ram, 256k of flash. The bsp works, we just don't enable the LCD sections.

Our application will run with MQX_ROM_VECTORS   0 in the user_config.h file, but we have to move the application into the next 64kb boundary to implement the boot loader. So it looks like the address of 0x1FFFF_0800 would be good for the RAM. Once I add the changes to the lcf file, it compiles and links, but nothing works. So I thought that the lcf additions were wrong or that I had to do the copy to RAM of the vector table. But it makes sense that mqx would do this. So the only thing left is that my lcf file is wrong. Should I delete this section below?

I worked through the vector table and it is the same as the k40 as far as I can see.

I tried the various example bootldrs for the tower and the USB won't fire on the call backs, so I gave up and will use our own code for the USB driver, MFS and the flash driver as a loader.

KEEP_SECTION { .vectortable }

MEMORY {

....

} > vectorram

0 Kudos
Reply

2,404 Views
BryGuyH
Contributor IV

I don't know enough about the lcf format to answer that question (I use a different tool chain that uses scatter files instead) however when you say bootloader that brings up a whole slew of other items. Have you tried:

a) using the ram vectors without the bootloader

b) using the bootloader with relocated rom vectors

One item I have noticed is that when using a bootloader with mqx is that I had to put preprocessor directives around some parts of the bsp or else they would cause the system to hang. In my case I completely block _bsp_initialize_hardware() from executing if compiled for use with a bootloader (the kinetis watchdog has very specific parameters regarding when you're allowed to write to its registers without causing a fault).

Edit:

I didn't think to ask last night when I posted but I think to answer your questions more fully we would need to know more about your bootloader design. Typically I would not expect that the bootloader be required to share ram with the application. In fact ram vectors and bootloaders are different topics (there is no need to use ram vectors unless your application requires the ability to install interrupt functions directly into the vector table). That being said a bootloader needs to jump to the application's ROM base address and not it's RAM vector table (which would be unpopulated at that time).

0 Kudos
Reply

2,404 Views
Cdn_aye
Senior Contributor I

Hi Bryan

Everything fell apart and went sideways after my last post. Something went wrong with the debug system. We were getting Device Secured messages, and then memory failed to write errors. I changed out the chip (100 pin LQFP) thinking the hardware was damaged. After many rebuilds, and attempts to get back to square 1, I restored the mqx directory for this processor. And it started to work again. What a mess...; completely misleading and erroneous messages unrelated to anything remotely connected to the problem. My quess is that something was caused the driver to read or write at an incorrect memory boundary causing a fatal bus error an incorrect readings.

Back to my last problem.  I think I have somewhat worked it out. The bootloader has to be in the 0x0000_0000 to 0x0000_1000 range, protected. The btldr the copies the app vector table to ram. This would normally get done by mqx if this was the only task but since it is the boot loader that is built independent from the app, the btldr has to take the responsibility of moving the table, and pointing the vector registor to the RAM vectors. Well that is the theory... I will let you know if it works. I got this pieced together from the three boot loader appnotes, 4367, 4368, 4370. Each with a piece of the information.

My problem is the appnote code 4368 does not run on the tower; the usb call back does't fire. I will try again tomorrow with a new adapter for the flash drive. Who knows maybe it will work.

Thanks for the expertise, it helped a lot.

2,404 Views
DavidS
NXP Employee
NXP Employee

Hi Robert,

I'm using CW10.2 (with all updates applied), MQX3.8.1, TWR-K60n512, and the AN4368/code.

I too had issues at first.  I think the issue was AN4368 code developed and tested with CW10.1 and MQX3.8.  But that is a guess.

I found that the watchdog disable routine not functioning correctly in the MQX code and it seems to me that the compiler was changing the order of execution of the instructions to disable the watchdog which caused the watchdog not to disable.  At least with my setup.

I add "volatile" to each line of code and that corrected the issue and allowed the MQX application to work.

So now from POR the bootloader ran and enabled me to take a MQX3.8.1 applications S19 and have it programmed to 0x10000 correctly.  A POR them restarted the bootloader, it saw a valid application, and jumped to it OK.

The "fix" to MQX was in the kinetis_sysinit.c __init_hardware() and I added the "volatile":

      //DES must use volatile below or compile does out of order writes!!! Therefore watchdog not disabled!!!

      *((volatile unsigned short *)KINETIS_WDOG_UNLOCK_ADDR)      = KINETIS_WDOG_UNLOCK_SEQ_1;               

      *((volatile unsigned short *)KINETIS_WDOG_UNLOCK_ADDR)      = KINETIS_WDOG_UNLOCK_SEQ_2;

      *((volatile unsigned short *)KINETIS_WDOG_STCTRLH_ADDR)     = KINETIS_WDOG_DISABLED_CTRL;    

Changes I made to AN4368 code:

main.c

#if 0

//DES 0=test, 1=default code....Watchdog not good for testing but good for production bootloader

__RESET_WATCHDOG();

/* feeds the dog */ 

#endif

 

printf.c

#define DEST_CONSOLE (3)    //DES was (1)....having (3) let printf go to UART

 

derivative.h

#define TERM_PORT UART3_BASE_PTR    //DES was UART5_BASE_PTR...uses the ttyd UART

For the MQX test application I only changed the following in the linker file used to place app @0x10000:

MEMORY

{

   vectorrom   (RX): ORIGIN = 0x00010000, LENGTH = 0x00000400

   cfmprotrom  (R): ORIGIN = 0x00010400, LENGTH = 0x00000020

   rom         (RX): ORIGIN = 0x00010420, LENGTH = 0x0007FBE0  # Code + Const data 

For the MQX test application I only changed the following in the linker file used:

Once you are up and running to validate my efforts I'll chat with the MQX Development team.

Regards,

David 

0 Kudos
Reply

2,404 Views
Cdn_aye
Senior Contributor I

Hi David

I have the boot loader successfully reading from the USB drive on the k20. Now I need to add our app, but I would like to make your watch dog change first; I have read that is a problem for many people as well. I will also try Bryan's suggestion and just build with the vector table set to RAM. First I need to add your changes and rebuild mqx.

Can you tell me which directory the kinetis_sysinit.c file is located please? This file does not appear to be in an MQX directory. I can see the file in several example folders in the CW 10.3 installation. I am using CW10.3 beta 2.

I can see the file

C:\Freescale\CW MCU v10.3\MCU\lib\wizard_data\ARM\DataBase\runtime\kinetis_sysinit_p2.c

This appears to be the file being used in the example. But it is in the lib folder and I think MQX copies this file or creates it there automatically during builds; so it wouldn't work modifying this file. Also the extension is p2, which is what the source for the example is using.

Do I modify the MQX installation and rebuild or my app or the loader for the watchdog changes.

Thanks

Robert

0 Kudos
Reply

2,404 Views
DavidS
NXP Employee
NXP Employee

Hi Robert,

I messed up the above post.

It is not MQX code but the bootloader code!  I had too many projects opened in CW and assumed.  Sorry for confusion.

The code is in the following path for the bootloader:

USB_MSD_Host_bootloader\bootload_code\Source\Host\examples\common\kinetis\kinetis_sysinit.c

Regards,

David

0 Kudos
Reply

2,404 Views
BryGuyH
Contributor IV

While you could in fact do that, based on my understandig of your design, it is more work than you need to do. The vector table for the application will still get loaded by the application over any work you did in the bootloader. All the bootloader really needs to do is return the processor to as close to reset state as possible and jump to the ROM base (I.e reset vector) of the application.

0 Kudos
Reply