This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F28069:使用 McBSP 实现高速 UART

Guru**** 2348500 points
Other Parts Discussed in Thread: C2000WARE, MOTORWARE
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/904230/tms320f28069-implementing-high-speed-uart-with-mcbsp

器件型号:TMS320F28069
主题中讨论的其他器件:C2000WAREMOTORWARE

您好!

我们能够使用 C2000的 SCI 端口实现高速(3.75 Mbit/s) UART (接收/发送的每个字节都会生成中断)。 但是、由于我们以10kHz 的频率运行 InstaSPIN FOC 控制器、并且与此高速 UART 并行运行、因此主循环的代码始终会被 UART 接收/传输中断(每毫秒接收16字节/12字节)和 FOC 控制器中断中断打断。 这种行为会在中断外部运行的代码上产生不可忽略的延迟。

我们解决上述问题的想法是使用支持 DMA 的 McBSP 端口来实现此 UART、以便为主代码提供更多处理时间。 需要注意的是、UART 在我们的系统中具有最高优先级、传输必须每毫秒完成一次。

在开始实施之前、我们需要您在以下问题上提供帮助:

  • 是否可以使用 McBSP 和 DMA 实现高速 UART (目标= 3.75Mbit/s)?
  • 如果是、您是否有任何可以加快开发速度的示例?
  • 如果否:
    • 有哪些限制?
    • 是否有任何其他方法可以改进当前的 UART 解决方案并缩短处理时间?

此致、
Johann

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Johann、

    如果您已经获得了具有 CPU 和 McBSP 的3.75Mbit/s、那么我肯定认为 DMA/McBSP 将能够做到这一点。  在 C2000Ware 中有一个 DMA/McBSP 示例、 这里是在线版本 、不过如果您更喜欢、也可以在本地安装中找到该版本。

    如果您对该示例或在系统中实施该示例有其他疑问、请告诉我。

    最棒的
    Matthew  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Matthew、您好!

    我们根本没有使用 McBSP。 目前、我们使用 SCI 和 RX/TX 中断达到3.75 Mbit/s。

    那么、您能否确认我们可以通过 McBSP + DMA 获得如此高速的数据呢?

    感谢你的帮助。

    此致、
    Johann

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Johan、

    我在 这里找到了支持 E2E 的帖子:https://e2e.ti.com/support/microcontrollers/c2000/f/171/t/787004?tisearch=e2e-sitesearch&keymatch=Single%20Phase%20UPS 、但我将总结正在使用的不同参数。   

    根据以下内容、使用 McBSP 作为 SPI 并使用 DMA 读取数据的速率应为3.75Mbps:

    1)此器件上的任何通信都受最大 GPIO 切换速率的限制、即25MHz、因此我们可以在此处进行通信

    2)对于 McBSP、主时钟速率被定义为2 * CLKG、其中 CLKG 是 McBSP/(1+ CLKGDV)的时钟源。  对于 SPI 模式、您将使用 LSPCLK、其速度与 CPU 时钟一样快。  由于 LSPCLK 提供其他外设、我需要您对该速率以及它是否由其他外设指定进行评论。  在3.75MBps 下、我们应该有足够的余量、我们只需替换基于 LSPCLK 的 CLKGDV 合理值

    3)最后、McBSP 位于外设帧3 (SPI 在 PF2上)上、两个都有0WS 写入、但有2个 WS 读取。  同样、由于 DMA 和 LSP 时钟以90MHz 的全时钟速率运行(假设 MCU 时钟为90MHz)、因此该帧的读取速率上限为30MHz、这对于您的数据速率而言绰绰有余。  如果您的 LSPClock 较低、我们也可以计算出这方面的数学原理、但我们应该能够做到这一点。

    4)实施、正如我提到过的、C2000Ware 中有一些示例、但 DMA 完全能够独立于 CPU 处理 McBSP 数据流。  即有 McBSP 发送和接收信号的 DMA 输入、以便它可以捕获数据。  然后、您可以选择 DMA 何时应将其 ISR 触发到主 CPU 以进行您需要对任何数量的数据(即一个或多个接收的数据)执行的任何数据处理。

    虽然 C2000Ware 中提供了 DMA 示例、但如果您希望根据您需要执行的操作提供一些特定的配置建议、我也很乐意为您提供相关帮助。

    如果您有其他问题、请告诉我。

    最棒的
    Matthew

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Matthew:

    感谢您的详细输入。

    不过、您将讨论 SPI、但在本例中、我们希望 通过 McBSP 实现 UART。

    您的观点是否也适用于通过 McBSP 的 UART? 如果是、您在上述观点中对 SPI 是否有任何差异?

    此致、
    Johann

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我认为您无法使用 McBSP 实现 UART。 McBSP 位于其基础同步端口中、在接收时需要时钟输入。

    对于更高的传输速度、您必须更改传输总线。 具有28069 SPI 端口是最明智的选择、因为您可以在 SPI 模式下使用带有 McBSP 和 McBSP 的 DMA。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Johann、

    首先、我要对上述响应中的错误表示歉意;因为我们在 McBSP 中有一个本地 SPI 模式、并且由于 DMA 和我错误阅读您的帖子、我们经常会遇到这个问题。

    我想看看 TI 内部是否有在另一个 TI 处理器上实现的应用手册。  我的经验是、我们的器件上的 McBSP 逻辑是相同的;但我想确保这一点。

    为了节省时间,如果您想查看  http://www.ti.com/lit/spra633 ,请点击此处查看应用手册。

    简而言之、限制因素是、无论我们的 McBSP/SPI 模式数据速率是多少、都需要被16分频、因为我们将使用1个 SPI 时隙进行16位传输。  有一些 CPU 开销、但我认为我们可以在 DMA 中处理这一问题。

    最棒的

    Matthew

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    大家好、

    出于某些原因、上述链接无法正常工作、请在此处查找文档:  

    此致、

    Ambroise

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Matthew、您好!

    最后、我们将使用 DMA 选择 SPI over McBSP、因为与 UART 相比、SPI 似乎更"本机"、这更有意义。

    因此、我们将实现从器件 SPI。

    我已经在基于  Example_2806xMcBSP_SPI_DLB  和  Example_2806xMcBSP_DLB_DMA 的代码中集成了 McBSP 、但使用了我自己的库、因为我的代码基于 C2000 Motorware 项目。

    我试图让它全天工作、但我完全无法与一位大师沟通。 主器件尝试向从器件(McBSP)发送18个字节、但 McBSP 似乎只在第一个时钟上升沿做出反应。 之后、MISO 线路保持在逻辑低电平。 我已经检查了 McBSP 和 DMA 寄存器、以查看传输期间和传输之后是否出现任何状态、但是所有寄存器保持不变(位不变)。

    在主器件侧、我们实现了一项功能、即在4个字节后在2个以上的位期间释放 NCS 引脚、以满足 McBSP 要求。

    这是我开发的代码。

    GPIO 配置(使用的 GPIO 为50、51、52和53)、设置为 McBSP 功能+异步限定。

    GPIO =(GPIO_Number_e) HAL_GPIO_McBspMdxA;
    GPIO_setMode (obj->gpioHandle、GPIO、GPIO_50_Mode_MDXA);
    GPIO_setQualification (obj->gpioHandle、 GPIO、GPIO_Qual_异 步);
    
    GPIO =(GPIO_Number_e) HAL_GPIO_McBspMdrA;
    GPIO_setMode (obj->gpioHandle、GPIO、 GPIO_51_Mode_MDRA);
    GPIO_setQualification (obj->gpioHandle、GPIO、GPIO_Qual_Async);
    
    GPIO =(GPIO_Number_e) HAL_GPIO_McBspMclkxA;
    GPIO_setMode (obj->gpioHandle、GPIO、GPIO_52_Mode_MCLKXA);
    GPIO_setQualification (obj->gpioHandle、GPIO、 GPIO_Qual_Async);
    
    GPIO =(GPIO_Number_e) HAL_GPIO_McBspMfsxA;
    GPIO_setMode (obj->gpioHandle、GPIO、GPIO_53_Mode_MFSXA);
    GPIO_setQualification (obj->gpioHandle、GPIO、GPIO_Qual_Async); 

     McBSP 配置

    void
    HAL_setupMcBspA (HAL_Handle handle)
    {
    HAL_Obj * obj =(HAL_Obj *) handle;
    McBSP_obj * McBSP =(McBSP_obj *) obj->mcbspaHandle;
    
    McBSP->SPCPCR2 = 0x0000U;
    McBSP->SPCR1 = 0x0000U;
    
    //将发送器和步骤1复位。
    //----------------------------
    McBSP->SPCR2 &=~McBSP_SPCR2_XRST;
    McBSP->SPCR1 &=~McBSP_SPCR1_RRST;
    //步骤2:将采样率发生器置于复位状态。
    //----------------------------
    McBSP->SPCR2 &=~McBSP_SPCR2_GRST;
    //步骤3:对影响 SPI 操作的寄存器进行编程。
    //----------------------------
    McBSP->SPCR1 &=~McBSP_SPCR1_CLKSTP;
    McBSP->SPCR1 ||(2 << McBSP_SPCR1_CLKSTP_POS);//时钟停止模式,无时钟延迟。
    
    // SPI 模式0选择(低非活动状态、McBSP 在
    SCLK 的上升沿发送数据、在下降沿接收数据。
    McBSP->PCR 和=~McBSP_PCR_CLKXP;
    McBSP->PCR 和=~McBSP_PCR_CLKRP;
    
    McBSP->PCR 和=~McBSP_PCR_CLKXM;//时钟在 MCLKX 引脚上接收。
    
    //设置单相发送/接收帧。
    McBSP->XCR2 &&~McBSP_XCR2_XPhase;
    McBSP->RCR2 &&~McBSP_RCR2_RPHASE;
    
    //设置1个串行字的发送和接收帧长度。
    McBSP->XCR1 &&~McBSP_XCR1_XFRLEN1;
    McBSP->RCR1 &&~McBSP_RCR1_RFRLEN1;
    
    //将发送和接收数据包长度设置为32位。
    McBSP->XCR1 |=(0x05 <<McBSP_XCR1_XWDLEN1_POS);
    McBSP->RCR1 |=(0x05 <<McBSP_RCR1_RWDLEN1_POS);
    
    //选择 LSPCLK 作为采样率发生器的输入时钟。
    McBSP->PCR &=~McBSP_PCR_SCLKME;
    McBSP->SRGR2 |= McBSP_SRGR2_CLKSM;
    
    //将 LSPCLK 除以2 (McBSP 的最大授权频率)。
    McBSP->SRGR1 &=~McBSP_SRGR1_CLKGDV;
    McBSP->SRGR1 ||(1 << McBSP_SRGR1_CLKGDV_POS);
    
    // FSX 引脚是输入引脚,用于芯片选择。
    McBSP->PCR 和=~McBSP_PCR_FSXM;
    
    // FSX 引脚为低电平有效。
    McBSP->PCR |= McBSP_PCR_FSXP;
    
    // SPI 从站操作要求字段 XDATDLY 和 RDATDLY 设置为0。
    McBSP->XCR2 &&~McBSP_XCR2_XDATDLY;
    McBSP->RCR2 &&~McBSP_RCR2_RDATDLY;
    
    //步骤4:启用采样率发生器。
    //----------------------------
    McBSP->SPCR2 |= McBSP_SPCR2_GRST;
    
    HAL_usDelay (100);
    
    //步骤5:启用发送器和接收器。
    //----------------------------
    McBSP->SPCR2 |= McBSP_SPCR2_XRST;
    McBSP->SPCR1 |= McBSP_SPCR1_RRST;
    
    HAL_usDelay (100);
    } 

    DMA 配置

    #pragma DATA_SECTION (m_spiDmaTestRxBuf、"DMARAML5")
    #pragma DATA_SECTION (m_spiDmaTestTxBuf、"DMARAML5")
    uint16_t m_spiDmaTestRxBuf[9]={0U、0U、0U、0U、0U、0U、0U、0U、0U、0U、0U 0U、0U、0U、0U};
    uint16_t m_spiDmaTestTxBuf[9]={0xFEED、0xDEAD、0xBEEF、0xF00D、0xCAFE、 0x1234、0x5678、0xFACE、0xB00C};
    
    void
    HAL_setupMcBspADma (HAL_Handle handle)
    {
    HAL_Obj *(HAL_Obj *) handle;
    dma_obj *(DMA_obj *) dma =(DMA_bobj *) obj->dma->dmaHandle;
    
    enable_protect_register_write_mode;dma->DMA--> dma-|-|-|-|-(
    
    DMA---)
    
    
    
    
    
    dma->ch1.burse_size = 1u; //每个突发
    DMA 2个16位字->CH1.SRC_BURST_STEP = 1U;//递增1个16位地址。 在 dma->ch1.dst_burst_step =
    1U 之间;//递增1个16位 addr。 在 dma->ch1.transfer_size
    = 9U 之间;//每9个突发中断(= 18字节)。
    
    DMA->CH1.SRC_TRANSFER_STEP = 0xFFFFFFU;//减量返回 McBSP DRR2寄存器。
    dma->ch1.dst_transfer_step = 1U;//在突发中的每个字之后移至缓冲区中的下一个字。
    
    dma->ch1.SRC_ADDR_SHADDR_SHADDR =(UINT32_t)&obj->mcbspAHandle->DRR2;
    dma->CH1.SRC_beg_ADDR_SHADDR_SHADDR =(UINT32_t)&obj->mcbspAHandle->DRR2;// TODO (S):不需要检查。
    dma->ch1.dst_ADDR_SHADDADDR =(uint32_t)&m_spiDmaTestRxBuf[0];
    dma->ch1.dst_beg_ADDR_SHADDR =(uint32_t)&m_spiDmaTestRxBuf[0];// TODO (S):不需要-进行检查。
    
    //清除同步错误标志
    dma->ch1.control |=(1U <<7);
    
    //设置为最大值以避免任何源/目标绕回。
    DMA->CH1.SRC_WOP_SIZE = 0xFFFFFFU;
    DMA->CH1.DST_WOP_SIZE = 0xFFFFFFU;
    
    DMA->CH1.MODE ||(1U << 15);//启用通道中断。
    DMA->CH1.MODE |=(1U <<9);//在传输结束时生成中断。
    DMA->CH1.MODE |=(1U <<8);//启用外设中断事件。
    
    DMA->CH1.MODE |=(15U <<0);// DMA 中断源:MREVTA (McBSP 接收)。
    
    dma->ch1.control |=(1U <<4);//清除所有杂散中断标志。
    
    //通道2:McBSPA 发送
    //---------------
    
    dma->ch2.burse_size = 1u; //每个突发
    DMA 2个16位字->CH2.SRC_BURST_STEP = 1U;//递增1个16位地址。 在 dma->ch2.dst_burst_step =
    1U 之间;//递增1个16位 addr。 在 dma->ch2.transfer_size =
    9U 之间;//每9个突发中断(= 18字节)。
    
    DMA->CH2.SRC_TRANSFER_STEP = 1U;//在突发中的每个字之后移至缓冲器中的下一个字。
    DMA->CH2.dst_transfer_step = 0xFFFFFFU;//减量返回 McBSP DRR2寄存器。
    
    dma->ch2.SRC_ADDR_SHADDADDR =(uint32_t)&m_spiDmaTestTxBuf[0];
    dma->ch2.SRC_beg_ADDR_SHADDR =(uint32_t)&m_spiDmaTestTxBuf[0];// TODO (S):不需要-进行检查。
    dma->ch2.dst_ADDR_SHADDADDR =(uint32_t)&obj->mcbspAHandle->DXR2;
    dma->ch2.dst_beg_ADDR_shadow =(uint32_t)&obj->mcbspAHandle->DXR2;// TODO (S):不需要检查。
    
    //清除同步错误标志
    dma->ch2.control |=(1U <<7);
    
    //设置为最大值以避免任何源/目标绕回。
    DMA->CH2.SRC_WOP_SIZE = 0xFFFFFFU;
    DMA->CH2.DST_WOP_SIZE = 0xFFFFFFU;
    
    DMA->CH2.MODE |=(1U << 15);//启用通道中断。
    DMA->CH2.MODE |=(1U <<9);//在传输结束时生成中断。
    DMA->CH2.MODE |=(1U <<8);//启用外设中断事件。
    
    DMA->CH2.MODE |=(14U <<0);// DMA 中断源:MXEVTA (McBSP 传输)。
    
    dma->ch2.control |=(1U <<4);//清除任何伪中断标志。
    
    disable_protected_register_write_mode;
    } 

    其他重要信息:

    • LSPCLK 等于 SYSCLKOUT (90MHz)
    • 在配置 McBSP 之前、DMA 被配置并启动(两个通道)。
    • 在使用以下代码配置 McBSP (并且它们的处理程序被正确设置)后、DMA 中断(针对每个通道)被启用:
    void
    HAL_enableMcBspADmaInt (HAL_Handle handle)
    {
    HAL_Obj * obj =(HAL_Obj *) handle;
    
    PI_enableInt (obj->压 电极、PI_GroupNumber_7、PI_InterruptSource_DMA_CH1);
    PI_enableInt (obj->压 电极、 PI_GroupNumber_7、PI_InterruptSource_DMA_CH2);
    
    CPU_enableInt (obj->cpuHandle、CPU_IntNumber_7);
    } 
    • McBSP 和 DMA 外设被计时。
    • 我们尝试了从6MHz 到400kHz 的时钟频率:同样的问题。
    • 我能够使用我的代码(修改配置)制作 McBSP SPI 回送示例。

    问题1:能否查看 McBSP 和 DMA 配置?
    问题2:在我们的方法中、您是否看到其他缺失或可能有问题的东西?

    以下是与用于 McBSP 和 DMA 的 Motorware 兼容的最小驱动程序、以及使用 DMA 和 McBSP 外设时钟启用功能更新的 CLK 驱动程序:

    /cfs-file/__key/communityserver-discussions-components-files/171/mcbsp.h

    /cfs-file/__key/communityserver-discussions-components-files/171/mcbsp.c

    /cfs-file/__key/communityserver-discussions-components-files/171/dma.h

    /cfs-file/__key/communityserver-discussions-components-files/171/dma.c

    /cfs-file/__key/communityserver-discussions-components-files/171/clk.h

    /cfs-file/__key/communityserver-discussions-components-files/171/clk.c

    我在 HAL_Obj 结构(在 hal_obj.h 文件中)中添加了这两行:

    McBSP_handle mcbspaHandle;
    dma_handle; 

    我在 HAL_init 函数的末尾(在 hal.c 文件中)添加了这两行代码:

    obj->mcbspAHandle = McBSP_init (((void*) MCBSPA_base_ADDR、sizeof (McBSP_obj));
    obj->dmaHandle = dma_init ((void*) dma_base_ADDR、sizeof (dma_obj)); 

    我在 HAL_setupPeripheralClks 函数末尾(在 hal.c 文件中)添加了这两行代码:

    clk_enableMcbspAClock (obj->clkHandle);
    clk_enableDmaClock (obj->clkHandle); 


    此致、
    Johann

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    这是一个更新。

    我们尝试使用 McBSP 作为没有 DMA 的 SPI 从器件发送和接收一个字节、但现在我们无法使其正常工作。

    在 SPI 模式0 (CPOL = 0、CPHA = 1)下、主器件以大约200kHz 的时钟频率发送字节0x72 (仅用于测试目的)。 从器件应以字节0x00的全双工方式进行应答(McBSP 处于 CLKSTP= 10b、CLKXP= 0、CLKRP = 0定义的模式)。

    McBSP 不接收字节。 实际上、根据下面的图、似乎遗漏了一些位。 McBSP 仅在第二个时钟上升沿(以红色突出显示)开始通过 MISO 发送。

    为了确认我们的假设、我们尝试发送两个字节(0x72、0x84)。 在这种情况下、在寄存器 DRR1中接收到字节0xCA、这意味着对于 McBSP、读数从第3个时钟下降沿开始(以粉色突出显示)。 这证实了我们对拖延的怀疑。 该图如下所示。

    McBSP 配置与上一个帖子中描述的一样、但区别在于 RWDLEN1和 XWDLEN1现在为0 (8位)。 以下是 McBSP 寄存器(FYI)中的值:

    Q3:这种延迟来自哪里? 我们花了整整一天的时间来尝试解决这个问题、但我们的想法已经过时了。 请向我们提供您的支持。

    Q4:我们的 LSPCLK 为90MHz。 对于1的 CLKGDV、这是可以的吗?

    问题5:+请参阅上一帖子中的问题 Q1和问题 Q2。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Johann、

    只想提供更新、让您知道我仍在检查代码、它需要一些时间来解析 Motorware + McBSP 设置。   

    您能评论一下您为整个系统设置的 LSPCLK 速率吗?  虽然 LSPCLK 可以等于 SYSCLK (最大90MHz)、但根据数据表、有一个20MHz McBSP 时钟限制。  如果 LSPCLK = 90MHz、则 CLKG = 45MHz、超出规格。  您需要使 CLKGDV = 4才能获得18MHz CLKG 以满足规范要求(3个给出22.5MHz、但仍高于规范)。

    我将继续通过代码进行解析、我同意我们现在应该重点关注 McBSP/SPI 代码、并且一旦我们启动并运行命令、就可以将 DMA 代码添加到中。

    最棒的

    Matthew

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Matthew、您好!

    您能评论一下您为整个系统设置的 LSPCLK 速率吗?

    正如我之前的帖子中所提到的、实际  LSPCLK  速率为90MHz (= SYSCLKOUT)。

    虽然 LSPCLK 可以等于 SYSCLK (最大90MHz)、但根据数据表、有一个20MHz McBSP 时钟限制。  如果 LSPCLK = 90MHz、则 CLKG = 45MHz、超出规格。  您需要使 CLKGDV = 4才能获得18MHz CLKG 以满足规范要求(3个给出22.5MHz、但仍高于规范)。

    我们已经看到了这一限制、并且已经尝试将 CLKGDV 提高到4以上以使 CLKG 低于20MHz。 但这并没有解决问题。

    无论如何、我们已经尝试了您的建议(CLKGDV = 4)、即 SPI 主器件时钟频率为750kHz。 问题仍然存在。

    真正奇怪的是、McBSP SPI 从器件仅在第一个 SPI 时钟之后才在 MISO 上准备数据、而不是在检测到 nCS 引脚置位时直接准备数据(通常在其他 IC 上完成)。

    问:这个"1时钟延迟"来自哪里(XDATADLY 和 RDATADLY 为0)?

    问:McBSP 中是否有未记录的限制会导致这种行为?

    请理解、我们需要尽快解决这一问题、因为这是我们一方的一个阻碍点、而且我们目前正在耗尽想法。

    此致、
    Johann

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    同意在文档中、我们不应看到延迟。

    查看 PCR 寄存器、从您之前的帖子中、它的值为0x0008。  我认为、这应该是0x0208 (用于驱动 MCLKX 引脚)、因为 SPI 主 器件和接收时钟刚刚在内部采用、或者、如果我们需要考虑路径的任何延迟、应该是0x0308以从 MCLKR 引脚额外获取接收时钟。  我假设在这种情况下、SPI 时钟是从作为主器件的 F2806x 生成的、因此如果另一端的线路/从器件延迟不是太大、0x0208应该起作用。

    最棒的

    Matthew

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    根据文档、由于 F28069在我们的案例中是 SPI 从器件、因此 CLKXM (PCR 的位9)必须等于0 (正如我们到现在所做的那样)。

    因此、我显然不会让您使用0x0208或0x0308来设置 PCR、因为这意味着 CLKXM 将设置为1 (仅适用于 SPI 主器件)。

    我们正在尝试通过 McBSP 使 C2000作为 SPI 从器件运行、而不是 SPI 主器件...

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Johann、

    您回答正确、我得到了"Master / Slave (主/从)"设置交叉的 SPI Slave X-mit (SPI 从 X 发送)。  这两个位都应该被清除、并且在代码中是正确的。

    根据更多的调查、我认为我们正在针对时序/速度问题进行升级、而数据表中的一些措辞、特别是基于 GPIO 最大切换频率的20MHz 限制的注释使这一问题变得更加复杂。

    虽然该限制为 true、但在本例中、我相信它仅适用于来自系统 SPI 主器件的 CLKX 上的传入信号。  McBSP 逻辑本身只有 SYSCLK 的1/2。  因此、如果 LSPCLK 已经是/2、那么我们可以设置 CLKGDV =0;或者如果 LSPCLK = SYSCLK、我们只需要设置 CLKGDV = 1。  90MHz CPU 时钟的最大值为45MHz。

    对于 SPI 受控模式、这将特别重要、因为内部时钟将确定我们在 CLKX 引脚上对主时钟进行采样的速度。  在这方面有一个限制、 即内部逻辑可以检测/同步到的最大输入时钟为8个 CLKG 周期。  在本例中、如果我们有45MHz CLKG、我们必须将 SPI 主/输入时钟限制为45/8或5.625MHz。  我不相信这是您之前的图本身的问题、但当我要求您 减慢 CLKG (内部 McBSP 时钟)时、这可能会使事情变得更糟、因为我们正在放宽采样分辨率并可能违反上述要求。

    我还在 GSYNC 位(SRGR2寄存器中的位15)上找到了一条注释、对于 SPI 从机模式、我们需要将其设置为"1"、以使 CLKG 与 CLKX 信号同步。  此位当前已在您先前发送的设置屏幕截图中清除。

    我发现的另一点是发送和接收时钟的极性。  现在、我知道它们都设置为上升沿极性(CLKXP 和 CLKRP =0)。  文档对此并不十分清楚、但我认为在 SPI 从器件的情况下、我们应该保持 CLKRP =0、但开关 CLKXP =1为 C28x SPI 从器件将其数据发送回主器件提供半个周期的延迟。   

    让我们尝试上述所有操作、看看它是否解决了您在接收(导致消息错误)和传输上看到的延迟。

    最棒的
    Matthew

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Matthew、您好!

    由于时间对于这个项目至关重要、并且由于我们无法使 McBSP 作为 SPI 从器件工作、我们将其配置为 SPI 主器件、并且只需一天的时间即可使其与 DMA 配合使用。

    由于该解决方案似乎运行良好、我们暂时保留它、并搁置 SPI 从器件解决方案。

    现在、我有一个关于如何使用 McBSP SPI 定期高效启动 DMA 传输的问题。

    实际上、在我们的系统中、我们每1ms 启动5次4字节突发 DMA 传输。 为此、我们每1ms 执行以下过程以开始传输:

    1. 停止 McBSP。
      McBSP->SPCR2 &=~(1U <<7);
      McBSP->SPCR2 &=~McBSP_SPCR2_XRST;
      McBSP->SPCR1 &=~McBSP_SPCR1_RST;
      McBSP->SPCR2 &=~McBSP_SPCR2_GRST; 
    2. 设置 McBSP DMA 传输。
      enable_protected_register_write_mode;
      
      dma->DMACTRL |=(1 << 0);
      asm (" nop");
      
      //通道1:McBSPA 发送
      //---
      
      dma->ch1.burse_size = 1u; //每个突发
      DMA 2个16位字->CH1.SRC_BURST_STEP = 1;//递增1个16位地址。 在 dma->ch1.dst_burst_step =
      1之间;//递增1个16位 addr。 在 dma->ch1.transfer_size
      = 4U 之间;//每隔(4 + 1)个突发(= 20字节)中断一次。
      
      DMA->CH1.SRC_TRANSFER_STEP = 1;//在突发中的每个字之后移至缓冲器中的下一个字。
      DMA->CH1.dst_transfer_step = 0xFFFF;//减量返回 McBSP DXR2寄存器。
      
      dma->ch1.SRC_ADDR_SHADDADDR =(UINT32_t)&p_txBuf[0];
      dma->ch1.SRC_beg_ADDR_SHADDR =(UINT32_t)&p_txBuf[0];// TODO (S):不需要-要检查。
      dma->ch1.dst_ADDR_SHADDADDR =(uint32_t)&obj->mcbspAHandle->DXR2;
      dma->ch1.dst_beg_ADDR_shadow =(uint32_t)&obj->mcbspAHandle->DXR2;// TODO (S):不需要检查。
      
      //清除同步错误标志
      dma->ch1.control |=(1U <<7);
      
      //设置为最大值以避免任何源/目标绕回。
      DMA->CH1.SRC_WOP_SIZE = 0xFFFFFFU;
      DMA->CH1.DST_WOP_SIZE = 0xFFFFFFU;
      
      // DMA->CH1.MODE |=(1U << 15);//启用通道中断。
      DMA->CH1.MODE |=(1U <<9);//在传输结束时生成中断。
      DMA->CH1.MODE |=(1U <<8);//启用外设中断事件。
      
      DMA->CH1.MODE |=(14U <<0);// DMA 中断源:MXEVTA (McBSP 传输)。
      
      dma->ch1.control |=(1U <<4);//清除所有杂散中断标志。
      
      //通道2:McBSPA 接收
      //---------------
      
      dma->ch2.burse_size = 1u; //每个突发
      DMA 2个16位字->CH2.SRC_BURST_STEP = 1;//递增1个16位地址。 在 dma->ch2.dst_burst_step =
      1之间;//递增1个16位 addr。 在 dma->ch2.transfer_size
      = 4U 之间;//每隔(4 + 1)个突发(= 20字节)中断一次。
      
      DMA->CH2.SRC_TRANSFER_STEP = 0xFFFF;//再回到 McBSP DRR2寄存器。
      dma->ch2.dst_transfer_step = 1;//在突发中的每个字之后移动到缓冲器中的下一个字。
      
      dma->ch2.SRC_ADDR_SHADDR_SHADDR =(UINT32_t)&obj->mcbspAHandle->DRR2;
      dma->ch2.SRC_beg_ADDR_SHADDR_SHADDR =(UINT32_t)&obj->mcbspAHandle->DRR2;// TODO (S):不需要检查。
      dma->ch2.dst_ADDR_SHADDADDR =(UINT32_t)&p_rxBuf[0];
      dma->ch2.dst_beg_ADDR_SHADDR =(UINT32_t)&p_rxBuf[0];// TODO (S):不需要-要检查。
      
      //清除同步错误标志
      dma->ch2.control |=(1U <<7);
      
      //设置为最大值以避免任何源/目标绕回。
      DMA->CH2.SRC_WOP_SIZE = 0xFFFFFFU;
      DMA->CH2.DST_WOP_SIZE = 0xFFFFFFU;
      
      DMA->CH2.MODE |=(1U << 15);//启用通道中断。
      DMA->CH2.MODE |=(1U <<9);//在传输结束时生成中断。
      DMA->CH2.MODE |=(1U <<8);//启用外设中断事件。
      
      DMA->CH2.MODE |=(15U << 0);// DMA 中断源:MREVTA (McBSP 接收)。
      
      dma->ch2.control |=(1U <<4);//清除任何伪中断标志。
      
      disable_protected_register_write_mode; 
    3. 启用 DMA。
      enable_protected_register_write_mode;
      dma->ch1.control |=(1U <<0);
      dma->ch2.control |=(1U <<0);
      disable_protected_register_write_mode; 
    4. 启动 McBSP。
    McBSP->SPCR2 |= McBSP_SPCR2_GRST;
    waitMcBspstability();
    McBSP->SPCR1 |= McBSP_SPCR1_RST;
    McBSP->SPCR2 |= McBSP_SPCR2_XRST;
    waitMcBspStability();
    McBSP->SPCR2 |=(1U <<7); 

    当 DMA 传输完成(DMA RX 中断)时、两个 DMA 通道(RX 和 TX)都被禁用(中断内部):

    enable_protected_register_write_mode;
    m_halHandle->dmaHandle->ch1.control |=(1U << 1);
    m_halHandle->dmaHandle->ch2.control |=(1U << 1);
    disable_protected_register_write_mode; 

    实际上、我们正在尝试减少启动 DMA 传输所需的时间、换句话说、我们正在尝试减少每次传输前要设置/清除的外设数量。

    问:我们如何在不禁用外设并重新配置通道的情况下高效地每1ms 重新启动一个 DMA 事务?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Johann、

    很好的消息、您可以将其用于传输。   根据我的理解、所有 DMA 设置看起来都是正确的。

    在 DMA 的模式寄存 器中有一个位;被称为"连续"的位11、当传输计数= 0时、该位应满足您不需要重新启用 DMA 通道的要求。

    DMA 将自动重新启用并重新加载影子->活动状态,就像这是复位后的初始突发一样。  如果需要、可以禁用 DMA ISR、也可以将其保持启用状态、如果要动态启用、则可以在 PIE IER 中禁用 C28x 的服务。  在任一种情况下、使用连续位都会为您重新设置 RUNSTS=1。  TRM 第730页的状态图 对此进行了概述(位于底部)。

    最棒的

    Matthew