Search code examples
cusbbufferinterruptatmelstudio

Accessing a buffer always returns 0, although the actual value is visible in Atmel Studio Debugger


this is a really specific question which might not have a direct answer, so any idea is appreciated.

Background: I am developing an application for a SAME70Q21 Microprocessor using C in Atmel Studio. The application exchanges data via USB with a host PC. I used the ASF drivers provided with Atmel Studio to build a vendor-specific USB device and wrote a custom driver based on WinUSB. When receiving a data packet from the host, the receiver module copies the received packet using a DMA to a buffer which is specified by my program when starting the receiver. After that, an interrupt is called. Inside this interrupt my program is supposed to copy the message from the buffer to a message stack, then restart the receiver.

Problem: Now, whenever a message is received the program acts as if the buffer has no content. Copying the message from the the buffer returns zeros. Interacting with the buffer (buffer[0]++, buffer[0]+4 or whatever) causes the adressed value inside the buffer to jump to 0.

I've watched the program using the Atmel Studio Debugger. The buffer contains the received message, but apparently the Microcontroller can't access it. The message is visible in the Memory, too (see picture). I've also tried directly acessing the buffer adress using pointers and memcpy without any result. When i change a single value in the buffer using the Debugger, the whole buffer becomes available, but only until the next message is received.

Code of the interrupt handler:

void main_vendor_bulk_out_received(udd_ep_status_t status,
    iram_size_t nb_transfered, udd_ep_id_t ep)
{
    UNUSED(ep);
    if (UDD_EP_TRANSFER_OK != status) {
        return; // Error in USB module, abort without restarting the receiver
    }

    //signal main loop that a message has been received
    bulk_rx_received = true; 

    //this was a test, copy first value from the buffer bulk_rx_buf to a local var, this always returns 0
    uint8_t x = bulk_rx_buf[0];

    //this is supposed to copy the data to the message stack, but the copy will always contain only zeroes
    memcpy(message_stack[message_stack_pointer], bulk_rx_buf, BULK_BUFFER_SIZE);
    message_stack_pointer++;
    if(message_stack_pointer == 32){
        message_stack_pointer = 0;
    }

    //restart the USB endpoint service, contains pointer to buffer, its size, pointer to callback
    udi_vendor_bulk_out_run(bulk_rx_buf, BULK_BUFFER_SIZE, main_vendor_bulk_out_received);
}

Picture of the memory viewer, the received message is "RUNA"


Solution

  • I've found the solution: This was a mistake due to my inexperience with ARM-Type MCUs. After the DMA copies the USB data into the RAM, the Cache of the processor needs to be refreshed manually. The DMA does not trigger a refresh event.

    When using ASF, use

    SCB_InvalidateDCache_by_Addr(BULK_BUFER_ADRESS, BULK_BUFFER_SIZE);

    to force the MCU to refresh the cached version of the buffer.