[En-Nut-Discussion] Move NutLoadConfig() into main thread?
Philipp Burch
phip at hb9etc.ch
Tue Nov 4 21:48:49 CET 2014
Any other comments/suggestions/thoughts on this?
Regards,
Philipp
On 02.11.2014 22:39, Philipp Burch wrote:
> Hi Uwe!
>
> On 02.11.2014 21:37, Uwe Bonnes wrote:
>>>>>>> "Philipp" == Philipp Burch <phip at hb9etc.ch> writes:
>>
>> Philipp> Hi everyone, I'm using an I2C EEPROM as non-volatile storage on
>> Philipp> my board. Since Nut/OS and/or Nut/Net already contain
>> ...
>> Philipp> But I also needed a workaround/hack in my I2C driver to make
>> Philipp> that stuff work. The problem is that NutLoadConfig() is called
>> Philipp> during system initialization from the idle loop. The driver
>> Philipp> normally is interrupt-driven and waits for an event using
>> Philipp> NutEventWait(), but this crashes when called from the idle
>> Philipp> thread (NutThreadSwitch() causes a BusFault on the
>> Philipp> Cortex-M4).
>>
>> Unexpected crashed often result from a stack to small. Did you try with more
>> stack space?
>
> Stack size for both idle and main is set to 4096 bytes, which should be
> far more than is required.
> Single-stepping with the debugger revealed that when NutThreadSwitch()
> is called, the global runQueue is 0 (NULL). What then follows is
>
> //...
> /* Select thread on top of the run queue. */
> runningThread = runQueue;
> runningThread->td_state = TDS_RUNNING;
> //...
>
> and this surprisingly doesn't fault. I don't really understand that, as
> the second line is a write directly into flash space (address 0x15
> according to the debugger). But in the next inline-ASM block, the last
> instruction to restore the registers crashes:
>
> //...
> /* Restore context. */
> #if (__CORTEX_M >= 0x03)
> __asm__ __volatile__( /* */
> "@ Load context\n\t" /* */
> "ldr sp, %0\n\t" /* Restore stack pointer. */
>
> #if defined (MCU_USE_CORTEX_FPU)
> "ldmfd sp!, {r4}\n\t" /* Get saved FPU status... */
>
> "vmsr fpscr, r4\n\t" /* ...and save back. */
> "vpop {s16-s31}\n\t" /* Restore FPU registers. */
> #endif
>
> "ldmfd sp!, {r4}\n\t" /* Get saved status... */
> "msr xpsr_nzcvq, r4\n\t" /* ...and save execution and
> application status in psr. */
> "cpsie i\n\t" /* ...enable interrupts */
> "ldmfd sp!, {r4-r11, pc}\n\t" /* Restore registers. */
> ::"m"(runningThread->td_sp) /* */
> );
> //...
>
> Seeking for the cause of runQueue being 0, I found the NutEventWait()
> function. Unless the queue has been signaled, program flow continues
> along the lines
>
> //...
> /*
> * Remove the current thread from the list of running threads
> * and add it to the specified queue.
> */
> NutThreadRemoveQueue(runningThread, &runQueue);
> NutThreadAddPriQueue(runningThread, (NUTTHREADINFO **) qhp);
> //...
>
> The first line makes runQueue 0x0 and the second one doesn't change
> that. I think this is basically correct operation, but then
> NutThreadResume() should not try to switch to the next thread in the
> runQueue when it is empty.
>
> Cheers,
> Philipp
> _______________________________________________
> http://lists.egnite.de/mailman/listinfo/en-nut-discussion
>
More information about the En-Nut-Discussion
mailing list