title: Cortex-M4F lazy FPU stacking
body: <p>I'm writing threading code for a Cortex M4F. Everything's working and I'm now looking into making FPU context switching more efficient via lazy stacking.</p>
  
  <p>I've read ARM's <a href="http://infocenter.arm.com/help/topic/com.arm.doc.dai0298a/DAI0298A_cortex_m4f_lazy_stacking_and_context_switching.pdf" rel="nofollow noreferrer">AN298</a> and I implemented the alternative approach based on disabling FPU and handling UsageFault, but the lower (<code>S0-S15</code>) registers are not being saved/restored correctly by the hardware. I think the problems lies in figure 11:</p>
  
  <p><a href="https://i.stack.imgur.com/srLf2.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/srLf2.png" alt="Figure 11 Context switching"></a></p>
  
  <p>According to this, when PendSV runs <code>FPCAR</code> should point to the space reserved in Task A's stack. But as I see it, since <code>CONTROL.FPCA</code> is high in Task C, <code>FPCAR</code> will be updated to point to Task C's stack when entering PendSV. If so, <code>S0-S15</code> and <code>FPSCR</code> will be saved to Task C's stack instead of Task A's, which is of course not correct.</p>
  
  <p>Am I missing something here, or is the appnote wrong?</p>
  
  <p>One a side note, I checked some open source RTOSes. FreeRTOS and mbed RTOS always stack <code>S16-S31</code> during the context switch, resulting in automatic <code>S0-S15</code> stacking, i.e. they make use of lazy stacking only to reduce interrupt latency but do full state preservation for tasks (as in the first approach outlined in the appnote). The TNKernel port for M4F uses the UsageFault approach, but fully saves/restores <code>S0-S31</code> via software, effectively bypassing any problem with <code>FPCAR</code> (at the cost of 48 load/stores instead of 32, the 16 hardware ones get overwritten on restore). Nobody seems to be using the UsageFault approach while only preserving <code>S16-S31</code>.</p>
  
  <p>(By the way, this is also posted at <a href="https://community.arm.com/thread/10325" rel="nofollow noreferrer">ARM Community</a>, but a lot of questions seem to go unanswered there. If I get an answer there, I'll replicate it here, too)</p>