Closed simonjwright closed 5 years ago
On 9/9/2018 10:04 AM, Simon Wright wrote:
I had a problem with Certyflie in that after a considerable time (an hour, maybe) I’d get an assertion failure in the postcondition of the |Clear_Status| call at the end of |DMA_Interrupt_Controller.Interrupt_Handler|, because the |Half_Transfer_Complete_Interrupt| hadn’t cleared. (I do question whether it’s OK to use assertions as a check on whether some external hardware behaved as expected? on the other hand, what else to do?)
Yes indeed, sometimes postconditions cannot be used because the hardware does something unexpected, but in general I think they are a good thing here too. During development, they helped me determine that what I thought would happen really did happen. And they serve as good documentation.
I don't know why the Half_Transfer_Complete status flag didn't clear though. To me this is a good reason for the postconditions, in that something in need of exploration is noticed.
I made this change, then changed the Certyflie code to enable all interrupts except |Half_Transfer_Complete_Interrupt|, and the drone ran without error for two hours. (The Crazyflie code only enabled |Transfer_Complete| last time I looked).
You might wonder whether to eliminate |STM32.DMA.Start_Transfer_With_Interrupts| and simply give |Start_Transfer| the same |Enabled_Interrupts| parameter? I could add that to this request if considered helpful.
I have some preference for the original approach with two distinct routines, one with interrupts and one without. It seemed a good distinction at the time anyway.
Pat
On 10 Sep 2018, at 23:35, Pat Rogers notifications@github.com wrote:
On 9/9/2018 10:04 AM, Simon Wright wrote:
I had a problem with Certyflie in that after a considerable time (an hour, maybe) I’d get an assertion failure in the postcondition of the |Clear_Status| call at the end of |DMA_Interrupt_Controller.Interrupt_Handler|, because the |Half_Transfer_Complete_Interrupt| hadn’t cleared. (I do question whether it’s OK to use assertions as a check on whether some external hardware behaved as expected? on the other hand, what else to do?)
Yes indeed, sometimes postconditions cannot be used because the hardware does something unexpected, but in general I think they are a good thing here too. During development, they helped me determine that what I thought would happen really did happen. And they serve as good documentation.
I have to agree!
I don't know why the Half_Transfer_Complete status flag didn't clear though. To me this is a good reason for the postconditions, in that something in need of exploration is noticed.
I'm fairly baffled about this, too. I wondered whether it was related to a very short transfer; I managed to check the status flags in the hardware register on one occasion while chasing this, and found both Transfer_Complete and Half_Transfer_Complete set. Perhaps the hardware won't clear HTIF if TCIF is set?
I made this change, then changed the Certyflie code to enable all interrupts except |Half_Transfer_Complete_Interrupt|, and the drone ran without error for two hours. (The Crazyflie code only enabled |Transfer_Complete| last time I looked).
I've been having real trouble chasing this down. At one point it was repeatable (failed within a minute or two), now I can't get it to fail at all. Something to do with optimisation levels? There's certainly an issue with comms to the nrf51, related I suspect to failing to pause DMA transfers to the nrf51 when requested (40 us deadline!) and therefore overrunning its buffers.
OK, just retried with PLATFORM_BUILD set to Production, ADL_BUILD to Debug, and got the error: the transfer count at the start of the transfer was 3, and the status flags were FEIF, HTIF, TCIF. Of course the hardware had had plenty of time to change the status flags after the breakpoint (in gnat_last_chance_handler) was hit.
FIFO error? Hmm, probably just the nrf51 couldn't read, since the FIFO wasn't enabled.
(Later) I made a more extensive patch, to only process a status flag if the corresponding interrupt is enabled; and then ran with just Transfer_Complete_Interrupt enabled. Looking good.
You might wonder whether to eliminate |STM32.DMA.Start_Transfer_With_Interrupts| and simply give |Start_Transfer| the same |Enabled_Interrupts| parameter? I could add that to this request if considered helpful.
I have some preference for the original approach with two distinct routines, one with interrupts and one without. It seemed a good distinction at the time anyway.
Would you prefer this patch if it adopted the same approach?
On 9/11/2018 3:15 PM, Simon Wright wrote:
(Later) I made a more extensive patch, to only process a status flag if the corresponding interrupt is enabled; and then ran with just Transfer_Complete_Interrupt enabled. Looking good.
Interesting!
You might wonder whether to eliminate |STM32.DMA.Start_Transfer_With_Interrupts| and simply give |Start_Transfer| the same |Enabled_Interrupts| parameter? I could add that to this request if considered helpful.
I have some preference for the original approach with two distinct routines, one with interrupts and one without. It seemed a good distinction at the time anyway.
Would you prefer this patch if it adopted the same approach?
Yes, sounds good.
Thanks Simon, good sleuthing!
Pat
Solved in #276
I had a problem with Certyflie in that after a considerable time (an hour, maybe) I’d get an assertion failure in the postcondition of the
Clear_Status
call at the end ofDMA_Interrupt_Controller.Interrupt_Handler
, because theHalf_Transfer_Complete_Interrupt
hadn’t cleared. (I do question whether it’s OK to use assertions as a check on whether some external hardware behaved as expected? on the other hand, what else to do?)I made this change, then changed the Certyflie code to enable all interrupts except
Half_Transfer_Complete_Interrupt
, and the drone ran without error for two hours. (The Crazyflie code only enabledTransfer_Complete
last time I looked).You might wonder whether to eliminate
STM32.DMA.Start_Transfer_With_Interrupts
and simply giveStart_Transfer
the sameEnabled_Interrupts
parameter? I could add that to this request if considered helpful.arch/ARM/STM32/drivers/dma_interrupts/stm32-dma-interrupts.ads (DMA_Interrupt_Controller.Start_Transfer): new parameter Enabled_Interrupts (defaulted to all interrupts).
arch/ARM/STM32/drivers/dma_interrupts/stm32-dma-interrupts.adb (DMA_Interrupt_Controller.Start_Transfer): likewise. Pass Enabled_Interrupts through to DMA.Start_Transfer_with_Interrupts.