Hi everyone,
So I have a question.
I have a ARM-M4 and for what I can tell this has both ARM and Thumb assembly. Meaning sometimes it interprets a 32 bit instruction as 2 16bit ones, some of the times.
How does that work? How does it know how to go about it?
I ask this because of a project.
I have a bootloader like code. And another application code.I configured the linker in the application code to start at 0x4000. To avoid developing the communication already, I converted the binary to a C array.
I pasted that array as a const in the bootloader code. The bootloader test code as of now just copies the array into the flash at 0x4000 and changes the vector table address to 0x4000 after that. Once all that's done, it jumps the PC to 0x4000.The jump is done this way - I created a empty function at 0x4000. This way I just have to call it to start the app code.
The problem seems to be that the first instruction is 32bits. It seems the PC is jumping each 16bits instead of each 32. And after a few jumps it just go crazy to a really big address in the RAM.I checked the memory and the copy was successful, exactly the same as the app code at 0x4000.
The Cortex-M series of embedded controllers does not support ARM instructions, it only supports Thumb-2 instructions. The instructions can be either 16 or 32 bits long but the 32 bit ones can be on halfword boundaries unlike ARM instructions. For instance a branch and link to a subroutine would be very limited if it had to fit into 16 bits. The embedded processors deal with memory and interrupts rather differently from the applications processors which support ARM instructions as well as Thumb-2 ones.
The Thumb-2 instruction set is an extension of the original Thumb. If you look up the documentation centre on the arm website it is a Cortex-M4 processor and the ARM architecture is ARMv7-M, and the supplier will have specific documentation for the chip.
Thanks for the answer daith,I really should start learning more about the core.
I use this MCU a lot but I came here because this seems to be more a core related problem, not really specific to this part.
Any idea why the code doesn't run? Maybe I forgot to set some registers? And how does the MCU know if it's a 16bit or 32bit instruction?
I am a bit confused. If you have been using it a lot I would have expected you to know that ARM and Thumb are encoded completely differently but I guess there's no need to ever come across ARM instructions when using an M4.
The best way of thinking about Thumb-2 is that the instructions are variable length in units of short words. The first 16 bits will say if another 16 bits are needed to compete the instruction. If the first short is 0xE800 to 0xFFFF then the next short is needed to complete the instruction. If somehow you have managed to generate ARM instructions from your tools then they'd all be full 32 bit words and most will start with 0xE but there will be many lower ones, e.g a BEQ would start 0x0A.
Hi Daith,
Well, I always use C, so I never needed anything lower level. I got a book now on the M3 and M4.Did a bit of quick reading and it seems what I am experiencing is a lockup (now why, I am still searching).
But back to instructions.
Thanks for that info. I did not find it before. What I saw recently in the book was that the bit[0] defines if it's a 16bit or 32bit instruction.
The dissassembly in my debugger shows the option to show mixed, ARM only and Thumb only. It's always in mixed, and when I switched to ARM only I noticed it shows some of the instructions as the same - I assume then that there are ARM instructios - or my disassembly is wrong and should never be in Mixed mode.When I had the same code copied (bootloader like application), the same code would appear as thumb only when the dissassembly is set to Mixed mode.
(I am being a bit confused right? sorry, not sure how to explain it).
Hello,
I feel strange for your procedure of the boot.
The vector table of ARM and Cortex-M4 is very different, and you seem to begin with ARM mode.
Regarding the M4 vector table, it contains no instructions but only a set of vector addresses. Therefore, to jump the vector causes the unpredictable behavior.
Also, as daith says, Cortex-M4 dos not include ARM native instruction set and you cannot begin with ARM mode,
I guess you would like to boot from Cortex-A something and would enter Cortex-M4 mode. If it was true, you should use BLX instruction to enter Cotex-M4 (i.e Thumb-2) mode.
Best regards,
Yasuhiko Koumoto.
The bit(0) in your book would be referring to the PC, not the instructions. If the bit in the PC is set then it is in Thumb mode, if 0 it is in ARM mode. The M4 and all the Cortex-M microprocessors only support Thumb mode.
What I was telling you was a way of looking at the hex of the instructions and seeing if they were for Thumb-2 or somehow were for ARM. If the words mostly start 0xE then it is very possibly ARM and you've set some option wrong in the code generation. The device might have ended eventually in a lockup if enough strange things happened but it is not starting in one and that is what you have got to look at so you got to trace in Thumb mode. I think though this is probably all okay if you've been doing things fine in the past.
More likely is that thing about bit 0 in the PC is causing the problem. Sorry I should have noted that as it is sometimes a PITA. If you have put in 0x4000 rather than 0x4001 as an address to branch to it will, depending on how it is done, very likely cause an exception.