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.

[参考译文] UART DMA TX 中断、只命中一次、然后崩溃

Guru**** 2582405 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/613313/uart-dma-tx-interrupt-hits-only-one-time-then-crash

主题中讨论的其他器件:MSP432P401R

您好!

需要有关以下问题的帮助。

我使用 DMA 定期执行 UART 传输。 在没有中断的情况下、它工作正常。 我尝试添加中断功能、但遇到了问题。

DMA 中断已被调用(void dmacb ())、但在该 faultISR 之后被调用...

我出了什么问题?

请参阅下面的代码和链接器文件

/*
=== uartecho.c ====
*/

#include 
#include 
/* XDCtools 头文件*/
#include 
#include 

/* BIOS 头文件*/
#include 
#include 
#include 

/* TI-RTOS 头文件*/
#include 
#include 
#include 

/*示例/板头文件*/
#include "Board.h"

#include 
#include 

/*默认故障处理程序的转发声明。 //
静态 void resetISR (void);
静态 void nmiISR (void);
静态 void faultISR (void);


//标记栈顶的链接器变量。 //
extern unsigned long __stack_end;


void dmacb ();
void dmaerr ();

#pragma retain (interruptVectors)
#interrma data_align (interruptVectors、128)
#pragma DATA_SECTION (pragma Vectors、".intvecs")
void (* const tVecteds[])(void)=
{
(void (*)(void)((uint32_t)&_stack_end)、
/*初始堆栈指针*/
resetISR、 /*重置处理程序 *
nmiISR、 /* NMI 处理程序 *
FAULTISR、 /*硬故障处理程序*/
0、0、0、0、0、0、0、
0、0、0、0、0、0、0、0、0、/* 11-20 */
0、0、0、0、0、0、0、0、0、/* 21-30 */
0、0、0、0、0、0、0、0、0、/* 31-40 */
0、0、0、0、dmaerr、0、0、/* 46 int dma err *
dmacb /* 49 int */
};


/*这是处理器在
复位事件之后首次开始执行时调用的代码*/*。 只执行绝对必要的设置,*/
/*之后调用应用程序提供的 entry()例程。 任何花式的*/
*操作(例如根据复位原因寄存

器做出决策、以及*/*复位该寄存器中的位)都只能由*/*应用程序控制。 */
void resetISR (void)
{
/*跳转至 CCS C 初始化例程。 *
_asm (".global _c_int00\n"
" _c_int00");
}


//这是处理器收到 NMI 时调用的代码。 这个*/
/*只需进入一个无限循环、保持
调试器检查*//*的系统状态。 */
static void nmiISR (void)
{
/* ULP Advisor 可免除故障陷阱*/
#pragma diag_push
#pragma CHECK_ULP ("-2.1")

/*输入无限循环。 *
while (1)
{
}

#pragma diag_pop
}


//这是处理器收到故障时调用的代码 */
/*中断。 这只是进入一个无限循环、保持系统状态*/
//*供调试器检查。 */
static void faultISR (void)
{
/* ULP Advisor 可免除故障陷阱*/
#pragma diag_push
#pragma CHECK_ULP ("-2.1")

/*输入无限循环。 *
while (1)
{
}

#pragma diag_pop
}


#define TASKSTACKSIZE 768
Task_Structt task0Struct;
Char task0Stack[TASKSTACKSIZE];
Semaphore_handle writeSem;
static dma_ControlTable dmaControlTable[8];

void dmacb ()
{
//map_dma_clearInterruptFlag (dma_channel_0);
///map_uart_clearInterruptFlag (eUSCI_A0_BASE、eUSCI_A_uart_transmit _interrupt);
//map_dma_disableInterrupt (INT_dma_INT1);
MAP_DMA_赋 值通道(DMA_CH0_EUSCIA0TX);
MAP_UART_clearInterruptFlag (EUSCI_A0_BASE、EUSCI_A_UART_Transmit _interrupt_FLAG);
//map_dma_disableInterrupt (dma_int1);
//uart_getEnabableInterruptStatus (eUSCI_A0_BASE);
}

void dmaerr ()
{
//


}void preparedma()
{
map_dma_enableModule();
MAP_DMA_setControlBase (dmaControlTable);
/*将 DMA 通道0分配给 EUSCI_A0_TX0 *
MAP_DMA_赋 值通道(DMA_CH0_EUSCIA0TX);

/*设置 TX 传输特性和缓冲器*/
MAP_DMA_setChannelControl (DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT、
UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
}

void UART_SEND_TEXT_DMA (char asci[]、int n)
{
MAP_DMA_setChannelTransfer (
DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT、
UDMA_MODE_BASIC、
ASCII、
(void *) map_spi_getTransmitBufferAddressForDMA (EUSCI_A0_BASE)、n);

map_dma_enableChannel (dma_channel_0);
}


void prepareInt()
{
MAP_Interrupt_enableMaster();
uint32_t adress1 = MAP_Interrupt_getVectorTableAddress ();
MAP_Interrupt_setVectorTableAddress (0x00020000);
MAP_DMA_赋 值中断(INT_DMA_INT1、DMA_CHANNEL 0);
MAP_DMA_enableInterrupt (INT_DMA_INT1);
MAP_Interrupt_enableInterrupt (INT_DMA_INT1);
}

void sendFn (UArg0、UArgarg1)
{
const eUSCI_UART_Config uartConfig =
{
EUSCI_A_UART_CLOCKSOURCE_SMCLK、 // SMCLK 时钟源
3、 // BRDIV = 78
0、 // UCxBRF = 2
0、 // UCxBRS = 0
EUSCI_A_UART_NO_奇 偶校验、 //无奇偶校验
EUSCI_A_UART_LSB_FIRST、 // LSB 优先
EUSCI_A_UART_One_stop_bit、 //一个停止位
EUSCI_A_UART_MODE、 // UART 模式
0//EUSCI_A_UART_oversampling_BAUDRATE_generation //过采样
};
char bubuff [256]、i;
for (i=0;i<255;i++) buff [i]=I;

MAP_WDT_A_HOLDTimer();
preparedma();

/*在 UART 模式下选择 P1.2和 P1.3 */
MAP_GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P1、
GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3、GPIO_PRIMARY_MODULE_FUNCTION);

/*将 DCO 设置为12MHz */
CS_setDCOCenteredFrequency (CS_DCO_FREQUENCY 24);

//![简单 UART 示例]
/*配置 UART 模块*/
MAP_UART_initModule (EUSCI_A0_BASE、uartConfig);

prepareInt();
/*启用 UART 模块*/
MAP_UART_enableModule (EUSCI_A0_BASE);

while (1)
{
UART_SEND_TEXT_DMA (缓冲区、256);
Task_sleep(2);
}
}

/*
=== main ====
*/
int main (void)
{
/*呼叫板初始化函数*/
Board_initGeneral();
Board_initGPIO();

writeSem = Semaphore_create (0、NULL、NULL);

/*构造 BIOS 对象*/
Task_Params taskParams;

Task_Params_init (&taskParams);
taskParams.STACKSIZE = TASKSTACKSIZE;
taskParams.stack =_task0Stack;
taskParams.instance->name ="回波";
taskParams.priority = 12;
Task_construct(&task0Struct,(Task_FuncPtr) sendFn、&taskParams、NULL);

/*打开用户 LED */
GPIO_WRITE (Board_LED0、Board_LED_ON);

/*启动 BIOS */
BIOS_start();

返回(0);
}

--------------------------------------------

--retain=闪存邮箱

存储器

主(RX):origin = 0x00000000,length = 0x00020000
APP_INTVEC (RX):origin = 0x00020000,length = 0x000000ff
INFO (RX):origin = 0x00200000,length = 0x00004000
SRAM_CODE (rwx):origin = 0x01000000、length = 0x00010000
SRAM_DATA (RW):origin = 0x20000000,length = 0x00010000

/*内存中的段分配*/

部分

.intvecs:> app_intvec
.text:> main
.const:> main
.cinit:> main
.pinit:> main

#ifdef __TI_Compiler_version__
#if __TI_Compiler_version__>=15009000
.TI.ramfunc:{}load=main、run=SRAM_code、table (BINIT)
#endif
#endif
.data :> SRAM_DATA
.bss:> SRAM_DATA
.sysmem:> SRAM_DATA
.stack:> SRAM_DATA (高电平)

针对 RTS 的 WDTCTL 寄存器的/*符号定义*
WDTCTL_sym = 0x4000480C;

 

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

    TI-RTOS 管理中断表。 您需要使用 Hwi 模块来创建中断。 您使用的是什么器件? 对于大多数器件、我们提供高级 UART 驱动程序。 您可以以 UART Echo 为例。

    Todd
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    >您使用的是什么设备?
    MSP432P401R

    >对于大多数器件、我们提供高级 UART 驱动程序。
    是的、但我在 Resource Explorer 中找不到 TIRTOS 的 UART DMA 示例

    >您可以以 UART Echo 为例。
    我确实做到了、它工作得很好、但我需要 UART + DMA

    >您需要使用 Hwi 模块来创建中断。
    会尝试... 但问题仍然是、为什么中断只命中一次?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    对于 MSP432、我们没有实施 DMA 版本的 UART 驱动程序。 我希望它运行一次、但当它退出时、它会使内核的内部状态机混乱。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的。 它很有用。。。

    我不使用中断、而是使用了一个 Hwi、它适用于 TX、但无法使其适用于 RX

    我的代码。 我是否错过了什么?

    静态 dma_ControlTable dmaControlTable[8];
    
    void preparedma()
    {
    map_dma_enableModule();
    MAP_DMA_setControlBase (dmaControlTable);
    /*将 DMA 通道0分配给 EUSCI_A0_TX0 *
    MAP_DMA_赋 值通道(DMA_CH0_EUSCIA0TX);
    
    /*设置 TX 传输特性和缓冲器*/
    MAP_DMA_setChannelControl (DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT、
    UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
    MAP_DMA_赋 值中断(INT_DMA_INT1、DMA_CHANNEL 0);
    MAP_DMA_disableInterrupt (INT_DMA_INT1);
    
    /*将 DMA 通道1分配给 EUSCI_A0_RX0 *
    MAP_DMA_赋 值通道(DMA_CH1_EUSCIA0RX);
    /*设置 RX 传输特性和缓冲器*/
    MAP_DMA_setChannelControl (DMA_CH1_EUSCIA0RX | UDMA_PRI_SELECT、
    UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_1);
    MAP_DMA_赋 值中断(INT_DMA_INT2、DMA_CHANNEL);
    MAP_DMA_disableInterrupt (INT_DMA_INT2);
    }
    
    void UART_SEND_DMA (char buy[]、int n)
    {
    MAP_DMA_setChannelTransfer (
    DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT、
    UDMA_MODE_BASIC、
    缓冲器、
    (void *) map_spi_getTransmitBufferAddressForDMA (EUSCI_A0_BASE)、n);
    
    MAP_DMA_enableInterrupt (INT_DMA_INT1);
    map_dma_enableChannel (dma_channel_0);
    }
    
    
    void UART_receive_dma (char buy[]、int n)
    {
    MAP_DMA_setChannelTransfer (
    DMA_CH1_EUSCIA0RX | UDMA_PRI_SELECT、
    UDMA_MODE_BASIC、
    (void*) map_SPI_getReceiveBufferAddressForDMA (EUSCI_A0_BASE)、
    缓冲器、n);
    MAP_DMA_enableInterrupt (INT_DMA_INT2);
    map_dma_enableChannel (dma_channel_1);
    } 

    void hwiUARTcb (uint32_t I)

    开关(I)

    情况 INT_DMA_INT0:
    MAP_DMA_disableInterrupt (INT_DMA_INT0);
    中断;
    案例 INT_DMA_INT1:
    MAP_DMA_disableInterrupt (INT_DMA_INT1);
    中断;
    案例 INT_DMA_INT2:
    Semaphore_post (writeSem);
    MAP_DMA_disableInterrupt (INT_DMA_INT2);
    中断;
    默认值:;

    MAP_UART_clearInterruptFlag (EUSCI_A0_BASE、EUSCI_A_UART_Transmit _interrupt_FLAG);
    //semaphore_post (writeSem);

    Hwi_handle prepareHwi (uint32_t i)

    hwi_handle hwiHandle;
    Hwi_Params HwiParams;
    ERROR_Block EB;
    ERROR_INIT (&EB);
    Hwi_Params_init (hwiParams);
    hwiParams.arg = i;
    hwiParams.instance->name ="DMA UART Hwi";
    hwiHandle = Hwi_create (i、hwiUARTcb、&hwiParams、&EB);
    if (hwiHandle ==空)

    system_abort ("Hwi 创建失败");

    返回 hwyle;

    空 sendFn1 (UArg0、UArgarg1)

    char bubuff [256]、i;
    for (i=0;i<255;i++) buff [i]=I;

    UART_Handle UART;
    UART_Params uartParams;

    /*创建一个数据处理关闭的 UART。 *
    UART_PARAMS_INIT (uartParams);
    uartParams.writeDataMode = UART_DATA_BINARY;
    uartParams.readDataMode = UART_DATA_BINARY;
    uartParams.readReturnMode = UART_return_full;
    uartParams.readEcho = UART_ECHO_OFF;
    uartParams.baudrate = 9600;

    UART = UART_OPEN (Board_UART0、uartParams);

    if (UART == NULL){
    System_abort ("打开 UART 时出错");

    preparedma();
    //预置 Hwi (INT_DMA_INT1);
    //预置 Hwi (INT_DMA_INT2);
    prepareHwi (INT_DMA_INT0);

    /*循环永久回显*/
    while (1)

    //uart_receive_dma (buff、2);
    //semaphore_pend (writeSem、BIOS_wait_forever);
    //uart_send_dma (buff、256);
    UART_WRITE (UART、缓冲区、256);
    //semaphore_pend (writeSem、BIOS_wait_forever);
    Task_sleep (1000);

    在 main() J 中,只需启动线程,即所有。

    RX 中断未被调用、TX -正常。

    感谢你的帮助。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是否将单个中断映射到 HWI? INT_DMA_INT0? 请记住、如果通道分配给 INT_DMA_INT1和 INT_DMA_INT2、则会在 INT_DMA_INT0中屏蔽它们。

    此致、
    Chris
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    >是否将单个中断映射到 HWI?
    是的、在 TI、没有经典的 Ira、只有 Hwi

    >INT_DMA_INT0?
    否、针对 TX 的 INT_DMA_INT1、针对 RX 的 INT_DMA_INT2

    您是否按照昨天的承诺运行了一些测试?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Yuliy、
    到目前为止、我尚未运行任何测试。 我希望利用 DMA 的现有驱动程序并配置 UART 以相应地触发 DMA。 我可能需要一周时间才能把这一点结合起来、但我会在取得进展时进行沟通。

    此致、
    Chris