1
votes

I'm writing bare-metal code for a microcontroller (MSP430 series) using the GCC/binutils toolchain and I'd like to use my linker script to fill unused interrupt vectors with the "loop forever" opcode (in dev, in production the "SW reset" opcode). I can't seem to make this happen.

Here's my linker script (or the relevant sections):

MEMORY {
  SFR              : ORIGIN = 0x0000, LENGTH = 0x0010 /* END=0x0010, size 16 */
  PERIPHERAL_8BIT  : ORIGIN = 0x0010, LENGTH = 0x00F0 /* END=0x0100, size 240 */
  PERIPHERAL_16BIT : ORIGIN = 0x0100, LENGTH = 0x0100 /* END=0x0200, size 256 */
  RAM              : ORIGIN = 0x1C00, LENGTH = 0x0800 /* END=0x23FF, size 2048 */
  INFOMEM          : ORIGIN = 0x1800, LENGTH = 0x0200 /* END=0x19FF, size 512 as 4 128-byte segments */
  INFOA            : ORIGIN = 0x1980, LENGTH = 0x0080 /* END=0x19FF, size 128 */
  INFOB            : ORIGIN = 0x1900, LENGTH = 0x0080 /* END=0x197F, size 128 */
  INFOC            : ORIGIN = 0x1880, LENGTH = 0x0080 /* END=0x18FF, size 128 */
  INFOD            : ORIGIN = 0x1800, LENGTH = 0x0080 /* END=0x187F, size 128 */
  FRAM (rxw)       : ORIGIN = 0x4400, LENGTH = 0xBB80 /* END=0xFF7F, size 48000 */
  VECT1            : ORIGIN = 0xFF90, LENGTH = 0x0002
  VECT2            : ORIGIN = 0xFF92, LENGTH = 0x0002
  VECT3            : ORIGIN = 0xFF94, LENGTH = 0x0002
  ... snip ...
  VECT54           : ORIGIN = 0xFFFA, LENGTH = 0x0002
  VECT55           : ORIGIN = 0xFFFC, LENGTH = 0x0002
  RESETVEC         : ORIGIN = 0xFFFE, LENGTH = 0x0002
  BSL              : ORIGIN = 0x1000, LENGTH = 0x0800
  HIFRAM (rxw)     : ORIGIN = 0x00010000, LENGTH = 0x00003FFF
}

SECTIONS
{
  __interrupt_vector_1   : { KEEP (*(__interrupt_vector_1 )) } > VECT1 =0x3C00
  __interrupt_vector_2   : { KEEP (*(__interrupt_vector_2 )) } > VECT2 =0x3C00
  __interrupt_vector_3   : { KEEP (*(__interrupt_vector_3 )) } > VECT3 =0x3C00
  __interrupt_vector_4   : { KEEP (*(__interrupt_vector_4 )) } > VECT4 =0x3C00
  __interrupt_vector_5   : { KEEP (*(__interrupt_vector_5 )) } > VECT5 =0x3C00
  __interrupt_vector_6   : { KEEP (*(__interrupt_vector_6 )) } > VECT6 =0x3C00
  ... snip ...
  __interrupt_vector_52  : { KEEP (*(__interrupt_vector_52)) KEEP (*(__interrupt_vector_timer0_b0)) } > VECT52 =0x3C00
  __interrupt_vector_53  : { KEEP (*(__interrupt_vector_53)) KEEP (*(__interrupt_vector_comp_e)) } > VECT53 =0x3C00
  __interrupt_vector_54  : { KEEP (*(__interrupt_vector_54)) KEEP (*(__interrupt_vector_unmi)) } > VECT54 =0x3C00
  __interrupt_vector_55  : { KEEP (*(__interrupt_vector_55)) KEEP (*(__interrupt_vector_sysnmi)) } > VECT55 =0x3C00
  __reset_vector :
  {
    KEEP (*(__interrupt_vector_56))
    KEEP (*(__interrupt_vector_reset))
    KEEP (*(.resetvec))
  } > RESETVEC
... and all the usual stuff, .data, .bss, etc ...

(0x3C00 is the "jump forever" opcode)

This doesn't seem to produce the sections at all if there's not at least one symbol on the input.

I tried messing around with . = .; and similar commands to get the section to be created even when there's nothing in the input sections, which sometimes worked, but I need the sections generated to be type PROGBITS and have the A flag set, otherwise they won't be loaded to the target. None of my attempts managed to produce this configuration.

What can I do to generate a section filled with 0x3C00, which is type PROGBITS and has the A flag set, when there is nothing in the input sections?

Thanks in advance for your help!

1

1 Answers

0
votes

Can you use the SHORT(0x3C00) syntax?

__interrupt_vector_1 : { SHORT(0x3C00) } > VECT1

This tells the linker to put two bytes 0x3C,00 into the section named __interrupt_vector_1 which is allocated in memory region VECT1. I don't think you need the KEEP directive anymore either. The name of the section, if not used, can be anything you want too. I usually match my sections to my memory regions in cases like this, e.g.

.vect1 : { SHORT(0x3C00) } >vect1

note the dot on the section name.

Also your VECT1 should be:

VECT1         (x) : ORIGIN = 0xFF90, LENGTH = 0x0002

Because it's executable code.