streaming of buffer that fills with DMA over USB_FS
I encountered a complex problem and I don't understand where should I start untangle it.
What I want to do:
I have a buffer (allocated in SRAM_1) that filling up with DMA. DMA pass TIM2_CCR1 value into buffer's cells.
Flow:
unsigned int dma_buffer[15360*4];
DMA1_Stream0->NDTR = 15360*4;
TIM2 input capture timer see event (high transition or low transition in my case I'm capture both), update CCR1 and kicks in DMA, that pass this(TIM2->CCR1) into dma_buffer, Increment addres, when next event occurs pas another value and so far and so forth.
when dma_buffer is half filled (thus (DMA1_Stream0 ->NDTR > 15360*2) -> half of the buffer length).
I want to transfer this half of buffer via USB_FS, the fastest way I found is:
for(int i = 0; i < 2; ++i) {
//SCB_InvalidateDCache();
CDC_Transmit_FS(buffer+SIZE*i, SIZE*sizeof(unsigned int));
while(((USBD_CDC_HandleTypeDef*)(hUsbDeviceFS.pClassData))->TxState != 0);
} // transfer via USB first half of buffer
and when DMA interrupt occurs I set flipFlag
void DMA1_Stream0_IRQHandler(void) {
// clear interrupt flag
DMA1->LIFCR |= (0x1 << 3) | (0x1 << 5);
dmaFlag++;
flipFlag++; // <-- indicates that second half of dma_buffer is already filled and we can transfer it
}after I transfer second part of dma_buffer:
for(int i = 2; i < 4; ++i) {
//SCB_InvalidateDCache();
CDC_Transmit_FS(buffer + SIZE*i, SIZE*sizeof(unsigned int));
while(((USBD_CDC_HandleTypeDef*)(hUsbDeviceFS.pClassData))->TxState != 0);
} // transfer second part of dma_bufferthe problem:
I have inconsistent data transferred like
first 15360 buffer entries 15360-15360*2 15360*2 - 15360*3 15360*3 - 15360*4
1-2-3-4 |5-6-7-8 |9 - 32 - 33 - 34 |35-36-37-38
the first two data chunks of SIZE(15360*sizeof(unsigned int)) are transferred correctly (first hald of dma_buffer).
but the third data chunk of SIZE starts correctly but soon became incoherent with the rest of data, it's like just some big number was added to.
Real life example:
dma_buffer[0] = 145 dma_buffer[1] = 604 dma_buffer[2] = 1103 dma_buffer[3] = 1604
......
dma_buffer[15360] = 7680113
......
dma_buffer[30720] = 15360115
.......
dma_buffer[31166] = 15583113
dma_buffer[31167] = 25692048 --> approx 10E6 incrementation ERROR
dma_buffer[31168] = 25694103
dma_buffer[31168] = 25694604 --> same ~500 delta from previous and starts going to the end
Any idea why is this happening? Both cache enabled (usb and uart transfer didn't seem to work without) I was trying invalidate cache before any data usages, but problem stays.
I have some ideas in my head:
- USB transfer can't share memory area with DMA that writing to that memory
- DMA halting until USB finish it transfer and but in that time CCR1 register is still getting new values so and after USB finish DMA starts writing that value to my buffer and that causes data incoherence
- Somewhat cause data corruption in dma_buffer but only highest bits not lowest
My experience in this fild is HIGHLY limited so I just don't know where to start, so any ideas and recommendations will be highly appreciated.
