IAR 78K0R port: random reboots

justdanpo wrote on Thursday, March 05, 2015:

I’ve just fixed a bug very hard to find.
IAR 78K0R port uses configMEMORY_MODE to detect if ES register should be saved/restored on a context switch.
The problem occurs when a project has near data model and far code model with a code placed in several 64K pages. As data model is near, configMEMORY_MODE should be set to 0. But a function exit code generated by IAR uses far data pointers. These pointers are used to retrieve how much function arguments should be removed from a stack.
When some task goes to a background inside a function exit code and another task or interrupt handler changes ES register, stack pointer of the first task becomes invalid.
To fix this issue portSAVE_CONTEXT and portRESTORE_CONTEXT in addition to configMEMORY_MODE should check the code model. But I’d rather always save ES register even when both code and data models are near.

rtel wrote on Thursday, March 05, 2015:

Thanks for taking the time to report this. I would be grateful if you could attach the updated port layer file so we can ensure we understand the fix correctly.

Regards.

justdanpo wrote on Friday, March 06, 2015:

FreeRTOS\Source\portable\IAR\78K0R\ISR_Support.h

portSAVE_CONTEXT macro

Original code:

#if configMEMORY_MODE == 1
	MOV       A, CS                 ; Save CS register.
	XCH       A, X
	MOV       A, ES                 ; Save ES register.
	PUSH      AX
#else
	MOV       A, CS                 ; Save CS register.
	PUSH      AX
#endif

For those who count each instruction cycle:

#if defined(__FAR_MODEL__) || (configMEMORY_MODE == 1)
	MOV       A, CS                 ; Save CS register.
	XCH       A, X
	MOV       A, ES                 ; Save ES register.
	PUSH      AX
#else
	MOV       A, CS                 ; Save CS register.
	PUSH      AX
#endif

__FAR_MODEL__ is a macro defined in assembler preprocessor options (just like __NEAR_MODEL__ in original demo project FreeRTOS\Demo\NEC_78K0R_IAR).
Also the condition (configMEMORY_MODE == 1) may be replaced by defined(__FAR_DATA_MODEL__).

The code I use at this moment:

	MOV       A, CS                 ; Save CS register.
	XCH       A, X
	MOV       A, ES                 ; Save ES register.
	PUSH      AX

I don’t care about 2 extra instructions for each save/restore context. Also some of my projects, which use NEAR code and data models, use far pointers (to access flash memory for example) so conditional compilation may also cause a bug.

portRESTORE_CONTEXT macro should be changed by the same way.

justdanpo wrote on Thursday, October 01, 2015:

OK, here is the file