首页 > 解决方案 > 访问缓冲区始终返回 0,尽管实际值在 Atmel Studio 调试器中可见

问题描述

这是一个非常具体的问题,可能没有直接的答案,所以任何想法都值得赞赏。

背景: 我正在 Atmel Studio 中使用 C 语言为 SAME70Q21 微处理器开发应用程序。该应用程序通过 USB 与主机 PC 交换数据。我使用 Atmel Studio 提供的 ASF 驱动程序构建了一个供应商特定的 USB 设备,并编写了一个基于 WinUSB 的自定义驱动程序。当从主机接收数据包时,接收器模块使用 DMA 将接收到的数据包复制到启动接收器时由我的程序指定的缓冲区。之后,调用中断。在这个中断中,我的程序应该将消息从缓冲区复制到消息堆栈,然后重新启动接收器。

问题: 现在,每当收到消息时,程序就好像缓冲区没有内容一样。从缓冲区复制消息返回零。与缓冲区(缓冲区 [0]++、缓冲区 [0]+4 或其他)交互会导致缓冲区内的寻址值跳转到 0。

我已经使用 Atmel Studio Debugger 观看了该程序。缓冲区包含接收到的消息,但显然微控制器无法访问它。该消息在内存中也可见(见图)。我还尝试使用指针和 memcpy 直接访问缓冲区地址,但没有任何结果。当我使用调试器更改缓冲区中的单个值时,整个缓冲区变为可用,但仅在收到下一条消息之前。

中断处理程序代码:

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);
}

内存查看器的图片,收到的消息是“RUNA”

标签: cusbbufferinterruptatmelstudio

解决方案


我找到了解决方案: 由于我对 ARM 型 MCU 缺乏经验,这是一个错误。DMA 将 USB 数据复制到 RAM 后,需要手动刷新处理器的 Cache。DMA 不会触发刷新事件。

使用 ASF 时,请使用

SCB_InvalidateDCache_by_Addr(BULK_BUFER_ADRESS, BULK_BUFFER_SIZE);

强制 MCU 刷新缓冲区的缓存版本。


推荐阅读