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.
您好!
我的设置为 EXP-MSP430FR5994 (用于时钟的外部晶振)、BQ76600 EVM (UART)、定制 BQ79616。 我使用 MSP430 DMA 进行 UART 接收。 我正在进入下面概述的比赛状态、并尝试解决方案。 唯一有助于实现 BQ 一致初始化的解决方案是在通过 UART 传输数据之前明确清除 DMAEN。
如果在 uartSend 中没有显式清除 DMAEN、BQ 初始化有时会在 BQ 自动寻址序列期间的第一次抛出读取后失败。
DMA 传输大小变量 uartRxLen 显示正确的值(并与寄存器宽度匹配);
本地 DMA 接收缓冲区 DMA_VALUE 的内容包含所有接收字节;但 DMA1SZ 寄存器中的值= 1、DMA ISR 不会触发。 我无法捕获故障发生的确切时刻。
下面列出的其他解决方案替代清除 DMAEN。 这些都不能帮助改善比赛条件:
1.在 DMA ISR 中从 LPM 中删除 EXIT (不存在 LPM 条目)
250ms BQ 测量时间(主计时器 ISR 当前为125ms)
3.在 UART ISR 上接收第一个字节;禁用 UART Rx ISR、然后为剩余的接收字节启动 DMA 传输。
我需要有关我可以尝试解决此问题的其他问题的指针。
Priya
1) 1)能否布置 main()函数? 在您到目前为止发布的内容中、我没有看到任何明显的控制流内容。
2)由于条件看起来足够清晰(DMA 看起来完成后 DMAEN 仍然打开)、接下来我将尝试"mousetrap "、 可能类似于:
if (BQUART_DMAxCTL & DMAEN) { // We expect it isn't asm volatile (" nop "); // Breakpoint here and see how we got here BQUART_DMAxCTL &= ~DMAEN; // Keep things rolling nonetheless }
这是主函数。 我将把"TRAP"代码放入 uartSend 函数中、查看我找到的内容。
#include "bspFuncs.h" #include "timer.h" #include "clock.h" #ifdef BQ_SPI #include <BQSpiInitFuncs.h> #include <BQSpiMeasure.h> #include "spiCommands.h" #endif #ifdef BQ_UART #include <BQUartInitFuncs.h> #include <BQUartMeasure.h> #include "uartCommands.h" #endif /** * main.c */ int main(void) { WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer Clock_Init(); #ifdef BQ_UART configure_pins_BQUart(); UART_Init(); DMA_Init(); #endif #ifdef BQ_SPI configure_pins_BQSpi(); SPI_Init(); #endif Timer_Init(); TA0_Start(); __enable_interrupt(); #ifdef BQ_SPI SpiReadyComm(); #endif #ifdef BQ_UART UartReadyComm(); #endif while(1) { if(1==Get_TimerFlag()) { Set_TimerFlag(0); #ifdef BQ_SPI BQ_SPI_APP(); //make measurements every 125 ms #endif #ifdef BQ_UART BQ_UART_APP(); //make measurements every 125 ms #endif updateTimers(); } } }
我无法在此感应断点处停止。 似乎 DMAEN 位上的转换正在帮助解决问题、否则 BQ 初始化过程有时会失败。
if ((BQUART_DMAxCTL & DMAEN) == 1) { // We expect it isn't asm volatile (" nop "); // Breakpoint here and see how we got here BQUART_DMAxCTL &= ~DMAEN; // Keep things rolling nonetheless }
如果我将此代码放入 uartSend 中、BQ 初始化失败、但未达到断点。
问题发生在 BQ 初始化序列的以下部分:
//SYNCRHONIZE 具有立即读取功能的 DLL
ReadReg (0、OTP_ECC_DATAIN1、autodr_RESPONSE_FRAME、1、0、 FRMWRT_STK_R);
while (dmaDataReady = 0);
这是发出的第一个 ReadReg 命令。 我在链接线程上上传的 uartCommands.c 文件中提供了高达 uartSend 的 ReadReg 命令流程。 其中大部分是 TI 提供的代码、修改后使用 MSP430 UART。
由于 DMAEN 不为1、此表单失败。 如果您需要使用比较、您可以尝试:
> if (((BQUART_DMAxCTL & DMAEN)!= 0){
if ((BQUART_DMAxCTL & DMAEN) != 0) { // We expect it isn't asm volatile (" nop "); // Breakpoint here and see how we got here BQUART_DMAxCTL &= ~DMAEN; // Keep things rolling nonetheless }
如果我在此代码中使用断点进行调试、由于某种原因、IDE 会话会直接进入此断点并停止。 我不明白为什么。 在它停止时、uartRxLen 为0。 与没有这种检查的情况不同、DMAEN 看起来始终为1。
除此之外、寄存器内容中没有任何问题。
DMA_Init()执行以下操作:
> BQUART_DMAxCTL |= DMADDT_0|DMADSTINCR_3|DMASRCINCR_0|DMASRCBYTE_WORD |DMADSTBYTE_WORD |DMADSTBYTE_WORD |DMA_TRIGGER_RISINGEDGE|DMAEN;
我不知道这是否会触发您的特定症状、但通常在您需要 DMAEN 之前设置 DMAEN 并不是一个好主意。
我将 DMA_Init 更改为
BQUART_DMAxCTL |= DMADD_0|DMADSTINCR_3|DMASRCINCR_0|DMASRCBYTE_WORD |DMADSTBYTE_WORD |DMADSTBYTE_WORD | DMA_TRIGGER_RISINGEDGE;
一旦我启动调试会话、执行仍会在断点处停止。 为什么 DMAEN 默认为1?
DMAEN 本身并不设为(1)、因此我的下一步是使用 CCS 搜索(工具栏项看起来像铅笔橡皮擦)来搜索 DMAEN、然后使用 uartSend 来查看我是否忘记了某些用法。
接下来是 uartSend (唯一设置 DMAEN=1的代码)处的断点、以查看调用栈中是否存在一些意外调用方。 此步骤将会更复杂一些、因为断点可能会干扰串行接收、但(因为您正在关闭原因)您不必多次执行此操作。
在项目中没有忘记调用 DMAEN 或 uartSend。
就调用堆栈而言、我该怎么做? 我在 DMA1CTL DMAEN 位上放置了一个连续的观察。 我可以看到 、在调试会话启动后、它很快变为1、并在断点处停止。 如何跟踪该写入 DMAEN 的源?
这是 CCS 中的堆栈使用视图
当您在断点处停止时、调用堆栈(我的 CCS 中的左上角视图)会显示名为 who 的用户列表、当前函数位于顶部。
我的操作假设是某些函数调用 uartSend、然后没有正确(或根本)等待 DMA 完成。 然后、对 uartSend 的下一个调用将跳过"悬空" DMAEN。 这意味着您正在尝试查找前一个调用方(可能是第一个调用方)、这在一般情况下并不容易、但您似乎具有非常可重复的序列、该序列会非常早地失败。
是的、看看左上角的情况、可以获得极大的帮助! 虽然只在一个位置调用 uartSend、但 WriteReg 和 ReadReg 都使用 uartSend。 只需为 ReadReg 启动 DMA 传输。 感谢您的帮助、非常感谢。