In ARM m0 core, what is the first instruction?

I am trying to learn how to use a cortex m0 processor. I have an stm32f0 development panel that allows me to view every bit of every address and easily upload a new binary. I read the lighted guides learning about many rules and functions, but still don't know where the program counter starts with reset, what type of argument it expects, and I don't even know how to write things like add or str / ldr in binary ... Does this mean basic knowledge from the guides I've read?

It says that m0 has a full top-down stack, but the origin seems to be at the other end (0x00000000). If the vector table could be explained to lay people as well, that would be great.

+3


source to share


2 answers


For all Cortex-Ms, the first two words on the memory map (respectively at addresses 0 and 4) should be your pointer to intial and the address of the first command you want to start.



Typically you put the stack at the highest RAM address and use the linker script to push the address of your program entry point to address 4.

+3


source


Full sized arms (cortex-A, etc.), address 0x00000000, for example, is a reset instruction that executes on its own, which is a little strange, you often see a list of addresses, but this is how they did it. For cortex-m, not only do they use an address list, but the hardware design is EABI compliant enough to allow you to inject C function names into the table and not have a small amount of assembly (other than the vector table itself).

So, for example, using the assembler gnu.

;@-----------------------
.cpu cortex-m0
.thumb
;@-----------------------

.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang

.thumb_func
reset:
    bl notmain
    b hang
.thumb_func
hang:   b .

      

Before digging in, you need to go to what is now at infocenter.arm.com and then architecture and then armv6-m get the armv6-m architecture reference manual (ARM ARM for v6m). These links have been around for a long time, but naturally they are subject to change, they will name it and differentiate between an architectural reference guide and a technical reference guide. Architectural references usually cover the family within this architecture. TRM usually covers a specific kernel number or revision of a specific kernel. it is probably worth getting this elsewhere on the info center page as well.

I am considering what I assume is rev C armv6m ARM ARM: ARM DDI 0419C

search for "vector table" in the document and find what may or may not be in the same section:

Table B1-4 Vector Table Format

This table shows that at offset 0, SP_main is in the address space. This is the reset value of the main stack pointer.

Then after that, the word offset in the table is the Exception number, and the word is 4 bytes in the hand world, so the exception number 1 is at offset 4 in the address space, the 2 exception is at 8, etc.

I always need to find the time. Also in the armv6m arm.

B1.5.2 Determine the exception number

where the exception number is 1 - reset 2 - nmi, etc. we take care of the reset.

so this means that at address 0x00000000 in ARMS ADDRESS SPACE we can, if we choose to preload the stack address, we can, if we want the stack to be set in bootstrap as well, but we don't need, one place has to do this, but not both.

Then, at 0x00000004 in ARMS ADDRESS SPACE, we will put the address of the reset handler.

So after building, compiling and linking the code in my example, I get

Disassembly of section .text:

08000000 <_start>:
 8000000:       20001000        andcs   r1, r0, r0
 8000004:       08000041        stmdaeq r0, {r0, r6}
 8000008:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 800000c:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 8000010:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 8000014:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 8000018:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 800001c:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 8000020:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 8000024:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 8000028:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 800002c:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 8000030:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 8000034:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 8000038:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 800003c:       08000047        stmdaeq r0, {r0, r1, r2, r6}

08000040 <reset>:
 8000040:       f000 f80a       bl      8000058 <notmain>
 8000044:       e7ff            b.n     8000046 <hang>

08000046 <hang>:
 8000046:       e7fe            b.n     8000046 <hang>

      

you can see that in the case of the assembler gnu putting .thumb_func in front of the label makes that label a function or address that could be called thus a bx or blx command, thus lsbit must be set which bx or blx must have the correct branch (bl doesn't care). which is automatically linked by the linker to the address in the vector table. reset at offset 0x40 gets, for example, 0x41.



Now why is this code not generated for address 0x00000000 ?! This is because you have to then look beyond the documentation to the documentation of the chip supplier, the hand does not make the chips they make the processor cores and some logic to support them, you go st or nxp or ti or whoever to find the rest specifically where the bootflash is in the address space. Undoubtedly, in this case, the flash with address 0x08000000 in the hand address space for normal boot is mapped to 0x00000000, some chips will have multiple boot flashes and depending on the brackets (input pins connected high or low or in different combinations) one or more flashes will be displayed at address zero forever or for a certain period of time.

crustal m0 (and m1) are (are) armv6m based on crust m3 and m4 based on armv7m. The huge difference is that the latter supports thumb2 extensions for the thumb instruction set (previously undefined instructions became the first half of two half-dictionary instructions of a 32-bit instruction, not to be confused with 32-bit mode instructions), and there is something like 150 or so thumb2 added to cortex m3 and then cortex m4 has a fraction of a floating point unit (only one floating point size, maybe one) and all the instructions that come with that (mostly overridden instructions). This makes life easier for cortex-m0, only 16-bit instructions (yes, bl is actually defined in the docs as two separate instructions that you can encode separately from each other if you like).

Currently ARM ARM armv6m also contains an instruction set definition

Chapter A5 Encoding Encoding Set Encoding

Looking at

A6.7.17 CMP (immediate)

      

(again, the section numbers in my case may remain the same or match in the future, their documents usually don't change much or from one to the other, but you never know).

The first thing to notice is the coding

Encoding T1 All versions of the Thumb instruction set.

      

this means all thumb supporters support this instruction (back from armv4 to present)

then the syntax is

CMP <Rn>,#<imm8>

      

that the unified syntax may differ from the syntax of these documents, it is also understood that ARM have their own toolchain, so the syntax, if defined, is specific to their assembler. Assembly language is not a standard that is specifically defined by the assembler, the program that parses it. Gnu assembler is a separate thing and does not have to conform to this doc, it basically does, but hand also started this one syntactic thing to allow some percentage of assembly language to be assembled for thumb, thumb2 extensions and hand instruction sets without rewriting, although you still quickly tie your hands if you don't indicate which one is somewhere.

you can see in this instruction that the upper bits should be 00101 bit 15:11, since the processor knows this comparison is immediate. Rn is a register from r0 to r7, whichever you are using (to access r8-r15, you need to use other mov instructions to allow the 16-bit instructions they had to store in most instructions for the lower 7 registers so that save a bit in instruction encoding) and then the bottom 8 bits are a direct constant value from 0 to 255 (other immediate hand / thumb encodings are not that straightforward and thumb versus hand uses different encodings, so you just have to read the manuals).

I highly recommend if you want to see the encoding, then write in assembler, then disassemble and let a reliably debuggable toolchain do the job, and then try to reverse engineer what you see and match it to the manual. The head scrapers are odd addresses, but they are documented (although not necessarily as you hoped) and then anything pc, pc related - TWO INSTRUCTIONS FORWARD, when you do something with it, it really isn't with a pipe, and for backward compatibility and set the standard that is the hand / thumb forward standard. so when calculating or reverse engineering the computation of the pc relative address, so your math is always 4 bytes off.

As with most processors, you are the programmer, or at least the programmer you trust to borrow their code, is the one that sets the stack pointer. You can put it wherever you want, the core of the hand itself and neither hand has any idea of ​​what the chipmaker will do with the implementation, and the compiler doesn't know or wants to know about all possible chips, so you programmer should say toolchain, which then tells the hand processor where you want the stack to be. Traditionally, with a top-down stack, you want to start at a high address. you start over by looking at the pop and pushing instructions and pseudo code to see the hand first decrements the number of registers by 4 times (for push), then writes to those addresses, then adjusts sp on the output. Therefore, if your ram has finished talking 0x2001FFFF,you can safely put the stack pointer at 0x20020000 and the first one that was pushed will be at 0x2001FFFC. (Well, not the first, but the very bottom of the stack is), other non-arm processors work differently and have different rules, some of which you cannot get from the stack pointer at all, some of them can, but the reset value is correct and some kind of weapons that you need to worry about. Full size arms you have multiple stack pointers to control, and you can also stack up or down, although I wouldn't go against grain just because you can.some of which you cannot get from the stack pointer at all, some of which you can, but the reset value is correct, and some kind of weapons you need to worry about. Full size arms you have multiple stack pointers to control, and you can also stack up or down, although I wouldn't go against grain just because you can.some of which you cannot get from the stack pointer at all, some of which you can, but the reset value is correct, and some kind of weapons you need to worry about. Full size arms you have multiple stack pointers to control, and you can also stack up or down, although I wouldn't go against grain just because you can.

+3


source







All Articles