-1

I am working on making a bootloader for a side project.

I have read in a hex file, verified the checksum and stored everything in flash with a corresponding address with an offset of 0x4000. I am having issues jumping to my application. I have read, searched and tried alot of different things such as the code here.

http://www.keil.com/support/docs/3913.htm

my current code is this;

int binary_exec(void * Address){
    int i;
    __disable_irq();
// Disable IRQs
for (i = 0; i < 8; i ++) NVIC->ICER[i] = 0xFFFFFFFF;
// Clear pending IRQs
for (i = 0; i < 8; i ++) NVIC->ICPR[i] = 0xFFFFFFFF;

// -- Modify vector table location
// Barriars
__DSB();
__ISB();
// Change the vector table
SCB->VTOR = ((uint32_t)0x4000 & 0x1ffff80);
// Barriars
__DSB();
__ISB();

__enable_irq();

// -- Load Stack & PC
binExec(Address);
return 0;
}

__asm void binexec(uint32_t *address)
{
    mov   r1, r0    
   ldr   r0, [r1, #4] 
   ldr   sp, [r1]     
   blx   r0"

}

This just jumps to a random location and does not do anything. I have manually added the address to the PC using keil's register window and it jumps straight to my application but I have not found a way to do it using code. Any ideas? Thank you in advance.

Also the second to last line of the hex file there is the start linear address record: http://www.keil.com/support/docs/1584.htm

does anyone know what to do with this line?

Thank you,

Eric Micallef

  • you have set the lsbit, this is a cortex-m4 yes so when you want to use blx or bx or mov pc or whatever you need to have the lsbit set to indicate you are branching to thumb code (which is the only instruciton set the cortex-m knows). perhaps that is what is going on? – old_timer May 06 '17 at 13:42
  • in the case of that last line in the hex file the lsbit is already set put that in a register say r0 then bx r0. – old_timer May 06 '17 at 13:43
  • how do I set the lsbit? – Eric Micallef May 06 '17 at 13:46
  • you use the or operation x=x|1; – old_timer May 06 '17 at 13:47
  • oh wow... I just realized that ls bit was least significant bit haha. I thought it was some fancy bit in some register. – Eric Micallef May 06 '17 at 14:07
  • unfortunately this did not work. any other suggestions? – Eric Micallef May 06 '17 at 16:52
  • why are you using blx instead of bx? and/or what is the rest of the code you have after blx, and what part of this is not working? why are you enabling irqs going into bootloaded code? that is for the code being loaded to do yes? show us a dump of an example vector table, an example Address, and the beginning of the pseudo reset code... – old_timer May 06 '17 at 18:09
  • hi @old_timer. Using keil I generated a hex file from a simple piece of code that just toggles and LED. I am sending this data over UART from a pi line by line and writing it to flash. my application right now just collects the data from UART stores it in a new location and then I want to jump to that new location. My understanding was that the vector table was reassigned with the command SCB->VTOR = ((uint32_t)0x4000 & 0x1ffff80); I also did not know I had to do a reset. I thought this was part of resetting your vector table and jumping to the new location. – Eric Micallef May 07 '17 at 01:01
  • I didnt say you had to do a reset you are trying to use the reset vector, the 0x4 offset into the vector table. Are you building that binary correctly for that target, what does your vector table show, what is the 32 bit value at offset 0x4 after you download that program (or even better dont bother with the download, just examine the program you are sending or use tools to disassemble/display that information and post it here). – old_timer May 07 '17 at 01:15
  • address 0x4000 in a cortex-m is generally flash, not always but generally, are you saying that is where you are downloading to? of so how or are you saying you are downloading to ram as in 0x20004000? – old_timer May 07 '17 at 01:23

1 Answers1

1

This is what I am talking about can you show us some fragments that look like this, this is an entire application just doesnt do much...

20004000 <_start>:
20004000:   20008000
20004004:   20004049
20004008:   2000404f
2000400c:   2000404f
20004010:   2000404f
20004014:   2000404f
20004018:   2000404f
2000401c:   2000404f
20004020:   2000404f
20004024:   2000404f
20004028:   2000404f
2000402c:   2000404f
20004030:   2000404f
20004034:   2000404f
20004038:   2000404f
2000403c:   20004055
20004040:   2000404f
20004044:   2000404f

20004048 <reset>:
20004048:   f000 f806   bl  20004058 <notmain>
2000404c:   e7ff        b.n 2000404e <hang>

2000404e <hang>:
2000404e:   e7fe        b.n 2000404e <hang>

20004050 <dummy>:
20004050:   4770        bx  lr
    ...

20004054 <systick_handler>:
20004054:   4770        bx  lr
20004056:   bf00        nop

20004058 <notmain>:
20004058:   b510        push    {r4, lr}
2000405a:   2400        movs    r4, #0
2000405c:   4620        mov r0, r4
2000405e:   3401        adds    r4, #1
20004060:   f7ff fff6   bl  20004050 <dummy>
20004064:   2c64        cmp r4, #100    ; 0x64
20004066:   d1f9        bne.n   2000405c <notmain+0x4>
20004068:   2000        movs    r0, #0
2000406a:   bd10        pop {r4, pc}

offset 0x00 is the stack pointer

20004000:   20008000

offset 0x04 is the reset vector or the entry point to this program

20004004:   20004049

I filled in the unused ones so they land in an infinite loop

20004008:   2000404f

and tossed in a different one just to show

2000403c:   20004055

In this case the VTOR would be set to 0x2004000 I would read 0x20004049 from 0x20004004 and then BX to that address.

so my binexec would be fed the address 0x20004000 and I would do something like this

ldr r1,[r0]
mov sp,r1
ldr r2,[r0,#4]
bx r2

If I wanted to fake a reset into that code. a thumb approach with thumb2 I assume you can ldr sp,[r0], I dont hand code thumb2 so dont have those memorized, and there are different thumb2 sets of extensions, as well as different syntax options in gas.

Now if you were not going to support interrupts, or for other reasons (might carry some binary code in your flash that you want to perform better and you copy that from flash to ram then use it in ram) you could download to ram an application that simply has its first instruction at the entry point, no vector table:

20004000 <_start>:
20004000:   f000 f804   bl  2000400c <notmain>
20004004:   e7ff        b.n 20004006 <hang>

20004006 <hang>:
20004006:   e7fe        b.n 20004006 <hang>

20004008 <dummy>:
20004008:   4770        bx  lr
    ...

2000400c <notmain>:
2000400c:   b510        push    {r4, lr}
2000400e:   2400        movs    r4, #0
20004010:   4620        mov r0, r4
20004012:   3401        adds    r4, #1
20004014:   f7ff fff8   bl  20004008 <dummy>
20004018:   2c64        cmp r4, #100    ; 0x64
2000401a:   d1f9        bne.n   20004010 <notmain+0x4>
2000401c:   2000        movs    r0, #0
2000401e:   bd10        pop {r4, pc}

In this case it would need to be agreed that the downloaded program is built for 0x20004000, you would download the data to that address, but when you want to run it you would instead do this

.globl binexec
binexec:
  bx r0

in C

binexec(0x20004000|1);

or

.globl binexec
binexec:
  orr r0,#1
  bx r0

just to be safe(r).

In both cases you need to build your binaries right if you want them to run, both have to be linked for the target address, in particular the vector table approach, thus the question, can you show us an example vector table from one of your downloaded, programs, even the first few words might suffice...

old_timer
  • 69,149
  • 8
  • 89
  • 168
  • hi @old_timer. I am not entirely surehow to give you what you are asking buuuuuuuuut I did get it to work. There was a setting in keil that specifies IROM1 and IROM2 space I did not realize that these had to be set. Sorry for the frustration that I caused thank yo for your help though! – Eric Micallef May 07 '17 at 17:11