0
votes

I am working on a project with the CodeWarrior for MCU v10.6 IDE. It is an Eclipse based IDE from NXP. The project targets a K21 SoC from NXP (precisely a MK21FN1M0M12, which embeds a cortex-m4, armv7-m). CodeWarrior is configured to use the ARM toolchain.

I am running into a crash related to thumb-interwork. This feature is enabled by the IDE and cannot be deactivated.

Since armv7-m only supports thumb2, using thumb-interwork does not seem to make sense in the first place. But I probably am missing something here. All the code is properly generated in thumb instructions.

I get trouble when making an indirect function call, through a pointer. The function code gets an odd address at link stage, which is OK (this indicates it is thumb code). However, when calling it through a pointer, a BLX instruction gets generated (I suppose the linker updates the original BL into a BLX here) AND the function pointer's value remains even! Since the pointer's value is even, the jump instructs the core to switch to ARM mode. Hence the crash.

I think the linker upgrades the BL into a BLX because of the thumb-interwork feature being activated. On CodeWarrior for MCU v10.6, this is forced, I cannot disable it. I am told that this is "required for processor" by the tool and cannot click the related checkbox (Properties->C/C++ Build->Settings, ARM CPU. The processor is set to "cortex-m4").

I do not understand why, since this is armv7-m. Moreover it seems to lead me into trouble. I think I am missing something here.

Could you please help me understand what is going on and/or tell me if there is a way to disable thumb-interwork on CodeWarrior?

Thanks and best regards,

Pierre

1
Disabling Thumb interworking will break every function call (the tools aren't forcing it on just for giggles). This is a bit of an XY problem, and you've got the wrong Y. Can you give a complete minimal reproducible example of actual problematic code?Notlikethat
Thank you @Notlikethat for your comment. Sorry to ask, but why would disabling thumb interworking break function calls? In other words, why are bx / blx required? I am going to try to produce such an example out of the project which is quite large.Pierre Baudemont
I think I have answered my question from my previous comment. According to ARM's information about bl and blx, only the latter can use a register as operand. Thus I now understand why blx is required and why removing thumb-interworking would break function calls.Pierre Baudemont
Well, in truth it's more that I misremembered the finer details of exactly which instructions are interworking or not :) The reality of what I had in mind is that you could only avoid interworking by targeting the obsolete pre-Thumb-2 TPCS ABI, which simply isn't supported on M-profile (the AAPCS ABI, which is inherently interworking, is effectively baked into the architecture). Anyway, I suspect the real problem lies in your C code, because the fact that the thing you're calling isn't a real function pointer (which would have the lsb set) smells of undefined behaviour from typecasts.Notlikethat
Thank you @Notlikethat for your response. I appreciate your help! I think you are right, something must be wrong in the C code. I have tried to reproduce the problem with a prototype but did not succeed yet. The idea is to store a function pointer inside a struct ("event handler"), along with a pointer to its argument. Those structs are stored inside a table. typedef struct { int (*fct)(void *param); void *param; } event_item_t; The fct pointer is wrong when calling a register function like: int event_register(int id, int (*fct)(void *), void *param) fct is evenPierre Baudemont

1 Answers

1
votes

@Notlikethat was right, my question was a bit of an XY problem.

My problem arose from using libraries built with GCC with CodeWarrior configured to use the Freescale's toolchain (ARM tools).

The function pointer with the LSB not set came from one of those libraries and was valued at the link stage by CodeWarrior. Since the linker properly put every function from those libs at odd addresses, I guessed that it should miss some information to detect that the faulty pointer was actually a function pointer.

Long story short, it turned out that the libraries were stripped, especially with the --strip-unneeded flag. I removed that flag and the linker did a perfect job!