2

I have a set of linker script sections for an interrupt vector table. The sections will be located in RAM and will be loaded into RAM by my code. As each vector must be at an absolute location, there is a separate section (and a separate memory region) for each vector.

Some vectors may not be used by the application, whilst others will. To ensure that the copy code still works I need to make sure that, if a vector is not present, the equivalent space in ROM (two bytes) is filled. I tried to do this by advancing the location pointer but of course this only affects the VMA and so doesn't help me at all.

How can I ensure that a section always takes up the required amount of space in ROM? i.e. how can I move the LMA on if there is no data in the section?

Any hints or tips would be greatly appreciated.

I have abridged my current linker script below:

OUTPUT_ARCH(msp430)
ENTRY(_start)

MEMORY {
  ROM (rx)         : ORIGIN = 0x9C02, LENGTH = 0x61FE
  VECT1            : ORIGIN = 0x5B80, LENGTH = 0x0002
  VECT2            : ORIGIN = 0x5B82, LENGTH = 0x0002
  ...
  VECT63           : ORIGIN = 0x5BFC, LENGTH = 0x0002
}

SECTIONS
{
  __interrupt_vector_1 : 
  { 
    __vectable_load__ = LOADADDR(__interrupt_vector_1);
    __vectable_start__ = .;
    __interrupt_vector_1__ = .;
    KEEP (*(__interrupt_vector_1))
    . = __interrupt_vector_1__ + 2;
  } > VECT1 AT> ROM
  __interrupt_vector_2 : 
  { 
    __interrupt_vector_2__ = .;
    KEEP (*(__interrupt_vector_2)) 
    . = __interrupt_vector_2__ + 2;
  } > VECT2 AT> ROM

  ...

  { 
    __interrupt_vector_63__ = .;
    KEEP (*(__interrupt_vector_63))
    KEEP (*(__interrupt_vector_sysnmi))
    . = __interrupt_vector_63__ + 2;
    __vectable_end__ = .;
  } > VECT63 AT> ROM
}
P Mendham
  • 241
  • 5
  • 12
  • I guess another way of asking this question is: how do I stop the linker from discarding the section without adding anything extra to it (if the vector is defined it must not be any bigger)? – P Mendham Sep 07 '16 at 11:41
  • 1
    This is an XY problem. Instead of having a single section for every vector, you should use a single **table** in your code in its single section. Then place this section at the appropriate address. You might want to have a look at typical startup code not only for the MSP430, but also other MCUs like ARM Cortex-M. – too honest for this site Sep 07 '16 at 13:42
  • I'd go with what @Olaf is suggesting. The typical way this is done is with a table defined in either an assembly file or a C file that gets placed in the interrupt vector section. You can hammer that square peg into the round hole if you use enough force, but it's easier to just use the round peg. – rjp Sep 07 '16 at 13:48
  • Thanks for the input. I would normally go for a single table in the actual code, I do on some other platforms, but I was trying to retain as much compatibility with the standard MSP430 toolchain as possible. The toolchain uses a specific GCC attribute to specify an interrupt handler which then directs the tooling to insert the correct preamble/return code but also sorts out the vector table entry and ensures that the interrupt service routine is in low memory. I could do all of that manually but I would be fighting the tools. I'd prefer to deviate from the standard as little as possible. – P Mendham Sep 08 '16 at 08:43

1 Answers1

1

I have created a work around. In retrospect it's obvious, but in case this helps anyone else, I will describe it here.

My location pointer advancement doesn't help because if there is no data in the input section the linker discards the output section. This means that no data will get added to ROM. I need there to be padding added to ROM because I need to the vector table to always be the same size. I worked around this by using the location pointer advancement but putting all of the interrupt vectors into a single section:

OUTPUT_ARCH(msp430)
ENTRY(_start)

MEMORY {
  ROM (rx)         : ORIGIN = 0x9C02, LENGTH = 0x61FE
  VECTABLE         : ORIGIN = 0x5B80, LENGTH = 0x007E
}

SECTIONS
{
  .vector_table :
  {
    __vectable_load__ = LOADADDR(.vector_table);
    __vectable_start__ = .;
    __interrupt_vector_1__ = .;
    KEEP (*(__interrupt_vector_1))
    . = __interrupt_vector_1__ + 2;
    __interrupt_vector_2__ = .;
    KEEP (*(__interrupt_vector_2)) 
    . = __interrupt_vector_2__ + 2;
    ...
    __interrupt_vector_63__ = .;
    KEEP (*(__interrupt_vector_63))
    KEEP (*(__interrupt_vector_sysnmi))
    . = __interrupt_vector_63__ + 2;
    __vectable_end__ = .;
  } > VECTABLE AT> ROM
}

Now the necessary padding will get added to both RAM and ROM provided that the vector table is not completely empty. If it is that doesn't bother me, it just doesn't get copied, the main thing is that vectors don't end up in the wrong places.

P Mendham
  • 241
  • 5
  • 12