2
votes

I am currently trying to develop my own bootloader for an Atmel SAM R21. My idea is to run the bootloader firstly, so it will decide if an update is needed to be performed or just jumping to the application. The main problem is that the Interrupt Vector Table is located at the 0x0000_0000 address, so it needs to be relocated just before the application code, so if the bootloader has a 8KB space set in the linker file and using the BOOTPROT fuse in that way (setting this fuse it is supposed that there will be some protection to the amount of memory selected through the fuse), the vector table should start at the 0x0000_2000 address. In order to relocate the vector table I pretend to use the VTOR register, which is an offset applied to the original table address (0x0000_0000). The assembly code is the following:

  asm(" LDR R0,=0xE000ED08 "); //VTOR ADDRESS
  asm("LDR R1,=0x00002000");   //OFFSET
  asm(" STR R1, [R0]");
  asm(" LDR R0,[R1] ");
  asm(" MOV SP, R0"); 
  asm(" LDR R0,[R1, #4]");
  asm(" BX R0");

LDR instruction gives me the following error: Error[Og006]: Syntax error in inline assembly: "Error[401]: Operand syntax error"

What am I doing wrong? Maybe I am trying to use ARM instruction instead of a Thumb one?

I will very appreciate any advise.

I am also doubting if once I get the Interrup Vector Table relocated, should I count with the Initial MSP value also? I want to mean, if the Interrupt Vector table starts at address 0x0000_2000 after being relocated, I should count 4(bytes) * Interrupt in order to know which should be the initial application address, shouldn't I? If someone knows something about this it would be nice. I know I am close (or I think so), but I need to clarify those points.

Edited 27/06/16 at 13:04. This instruction works LDR R0,[R1] So I guess it is something related to receive the 32 bits address into the register, but I don't understand why it is complaining about this.

SOLUTION:

As an answer to my question, someone posted that not all assembly directives can be used inlined, so I needed to create an assembler file, my_file.s In this file should be created a function to be called from outside, something like this:

#define _PORT_ASM_ARM_SRC
#define __ASSEMBLY__

;/****************************************************************************
;**                                                                         **
;**                           ASSEMBLY FUNCTIONS                            **
;**                                                                         **
;****************************************************************************/

  NAME   start_app

  RSEG   CODE:CODE(2)
  THUMB

  PUBLIC jump_to_app

;/***************************************************************************/
;/***************************************************************************/
;/* jump_to_app()
; * Jump to application function.
; */

jump_to_app:
  LDR R0,=0xE000ED08 ; Set R0 to VTOR address
  LDR R1,=0x00010000 ; User’s flash memory based address
  STR R1, [R0] ; Define beginning of user’s flash memory as vector table
  LDR R0,[R1] ; Load initial MSP value
  MOV SP, R0 ; Set SP value (assume MSP is selected)
  LDR R0,[R1, #4] ; Load reset vector
  BX R0 ; Branch to reset handler in user’s flash


  END

After doing this, the function prototipe should be included into a .h file of your project as a normal function, using something like this:

void jump_to_app(void);

Best regards,

Iván.

2
One of those lines is not like the others... From searching those error codes, it seems like you're using the IAR toolchain; check the IAR ARM assembler manual for the significance of whitespace in its syntax. - Notlikethat
Hello Notlikethat. The problem is that I have tried the same format in all. The STR for example doesn't report any error, happening only in the LDR. Anyway, I am going to check IAR ARM assembler manual. - Fulgor3
I'm talking about the line with the nonsensical instruction R1,=0x00002000, which happens to have the label "LDR" ;) - Notlikethat
Hello again. Nonsensical? I need the application starting address in order to set the MSP and later on the reset vector address which will contain the address with the first instruction to execute. I don't know if I am understanding you well, sorry :( - Fulgor3
@Notlikethat is trying to point out that you don't have a space character before "LDR" on your second line. Perhaps that is important because without the whitespace, "LDR" may get treated as a label instead of an instruction. - kkrambo

2 Answers

3
votes

There is nothing syntactically wrong with the assembly code above. If you put the assembly code into an asm file and assemble it, it will build (as to whether it does what you intended I have not checked).

For some reason the inline assembler does not like LDR Rd, =expr.

See the following quote from the IAR Embedded Workbench Help:

The pseudo-instruction LDR Rd, =expr is not available from inline assembler

Also from ARM:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472j/chr1359124248868.html

2
votes

SOLUTION:

As an answer to my question, someone posted that not all assembly directives can be used inlined, so I needed to create an assembler file, my_file.s In this file should be created a function to be called from outside, something like this:

#define _PORT_ASM_ARM_SRC
#define __ASSEMBLY__

;/****************************************************************************
;**                                                                         **
;**                           ASSEMBLY FUNCTIONS                            **
;**                                                                         **
;****************************************************************************/

  NAME   start_app

  RSEG   CODE:CODE(2)
  THUMB

  PUBLIC jump_to_app

;/***************************************************************************/
;/***************************************************************************/
;/* jump_to_app()
; * Jump to application function.
; */

jump_to_app:
  LDR R0,=0xE000ED08 ; Set R0 to VTOR address
  LDR R1,=0x00010000 ; User’s flash memory based address
  STR R1, [R0] ; Define beginning of user’s flash memory as vector table
  LDR R0,[R1] ; Load initial MSP value
  MOV SP, R0 ; Set SP value (assume MSP is selected)
  LDR R0,[R1, #4] ; Load reset vector
  BX R0 ; Branch to reset handler in user’s flash


  END

After doing this, the function prototipe should be included into a .h file of your project as a normal function, using something like this:

void jump_to_app(void);

Best regards,

Iván.