硬件:TMS320C6748 (创龙开发板)
bsp: bios_6_37_03_30
相对裸机版的Uart dma配置,SYSBIOS 版本配置较简单。
C6748 的uart dma 模式,TI 的裸机demo 和 GIO 接口都是定长接收(就是指定接收长度), 收完指定的长度才会返回,否则会阻塞住。我还没找到通过中断方式实现不定长接收,这里是一个字节一个字节的接收,然后通过消息队列缓冲,消息队列的长度即接收的数据长度,以此实现不定长接收。缓冲方式可以更具自己需求更换,比如循环buffer。
主要注意事项:
DMA 模式与查询模式的区别是,DMA模式需要先使能EMDA3 TC/CC 通道。初始化EDMA3,
然后再创建UART handle,
app.cfg 中要注意添加,
ECM 也就是EventCombiner, 把uart 事件映射到cpu中断
具体代码和cfg如下;供大家参考。
app.cfg
var Defaults = xdc.useModule('xdc.runtime.Defaults');
var Diags = xdc.useModule('xdc.runtime.Diags');
var Error = xdc.useModule('xdc.runtime.Error');
var Log = xdc.useModule('xdc.runtime.Log');
var LoggerBuf = xdc.useModule('xdc.runtime.LoggerBuf');
var Main = xdc.useModule('xdc.runtime.Main');
var Memory = xdc.useModule('xdc.runtime.Memory')
var SysMin = xdc.useModule('xdc.runtime.SysMin');
var System = xdc.useModule('xdc.runtime.System');
var Text = xdc.useModule('xdc.runtime.Text');
var BIOS = xdc.useModule('ti.sysbios.BIOS');
var Clock = xdc.useModule('ti.sysbios.knl.Clock');
var Swi = xdc.useModule('ti.sysbios.knl.Swi');
var Task = xdc.useModule('ti.sysbios.knl.Task');
var Semaphore = xdc.useModule('ti.sysbios.knl.Semaphore');
var Hwi = xdc.useModule('ti.sysbios.hal.Hwi');
var GIO = xdc.useModule('ti.sysbios.io.GIO');
var ECM = xdc.useModule('ti.sysbios.family.c64p.EventCombiner');
var ti_sysbios_hal_Cache = xdc.useModule('ti.sysbios.hal.Cache');
var xdc_runtime_Timestamp = xdc.useModule('xdc.runtime.Timestamp');
var iomFxns = "Uart_IOMFXNS";
var initFxn = "Uart2Init";
var deviceParams = "uartParams";
var deviceId = 2;
GIO.addDeviceMeta("/uart2", iomFxns, initFxn, deviceId, deviceParams);
var ti_sysbios_knl_Mailbox = xdc.useModule('ti.sysbios.knl.Mailbox');
/*
* Program.argSize sets the size of the .args section.
* The examples don't use command line args so argSize is set to 0.
*/
Program.argSize = 0x0;
/*
* Uncomment this line to globally disable Asserts.
* All modules inherit the default from the 'Defaults' module. You
* can override these defaults on a per-module basis using Module.common$.
* Disabling Asserts will save code space and improve runtime performance.
Defaults.common$.diags_ASSERT = Diags.ALWAYS_OFF;
*/
/*
* Uncomment this line to keep module names from being loaded on the target.
* The module name strings are placed in the .const section. Setting this
* parameter to false will save space in the .const section. Error and
* Assert messages will contain an "unknown module" prefix instead
* of the actual module name.
Defaults.common$.namedModule = false;
*/
/*
* Minimize exit handler array in System. The System module includes
* an array of functions that are registered with System_atexit() to be
* called by System_exit().
*/
System.maxAtexitHandlers = 4;
/*
* Uncomment this line to disable the Error print function.
* We lose error information when this is disabled since the errors are
* not printed. Disabling the raiseHook will save some code space if
* your app is not using System_printf() since the Error_print() function
* calls System_printf().
Error.raiseHook = null;
*/
/*
* Uncomment this line to keep Error, Assert, and Log strings from being
* loaded on the target. These strings are placed in the .const section.
* Setting this parameter to false will save space in the .const section.
* Error, Assert and Log message will print raw ids and args instead of
* a formatted message.
Text.isLoaded = false;
*/
/*
* Uncomment this line to disable the output of characters by SysMin
* when the program exits. SysMin writes characters to a circular buffer.
* This buffer can be viewed using the SysMin Output view in ROV.
SysMin.flushAtExit = false;
*/
/*
* The BIOS module will create the default heap for the system.
* Specify the size of this default heap.
*/
//BIOS.heapSize = 0x1000;
BIOS.heapSize = 0xa00000;
/*
* Build a custom SYS/BIOS library from sources.
*/
BIOS.libType = BIOS.LibType_Custom;
/* System stack size (used by ISRs and Swis) */
Program.stack = 0x2000;
/* Circular buffer size for System_printf() */
SysMin.bufSize = 0x200;
/*
* Create and install logger for the whole system
*/
var loggerBufParams = new LoggerBuf.Params();
loggerBufParams.numEntries = 16;
var logger0 = LoggerBuf.create(loggerBufParams);
Defaults.common$.logger = logger0;
Main.common$.diags_INFO = Diags.ALWAYS_ON;
System.SupportProxy = SysMin;
ECM.eventGroupHwiNum[0] = 7;
ECM.eventGroupHwiNum[1] = 8;
ECM.eventGroupHwiNum[2] = 9;
ECM.eventGroupHwiNum[3] = 10;
uart api
/*
* tlfs_hal_uart.c
*
* Created on: 2021-10-22
* Author: Bruce Su
*/
#include <xdc/std.h>
#include <xdc/runtime/Memory.h>
#include <xdc/runtime/Log.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/log.h>
#include <ti/sysbios/knl/task.h>
#include "tlfs_hal_uart.h"
#include <ti/sysbios/BIOS.h>
#include <string.h>
#include <ti/sysbios/io/GIO.h>
#include <uart/include/Uart.h>
#include <uart/include/UartLocal.h>
#include "PSC/Include/Psc.h"
#include <CSLR/cslr_psc_C6748.h>
#include <ti/sysbios/knl/Mailbox.h>
#include "TL6748.h"
#define UART2_HWI_NUM (12)
#define UART2_MSG_CNT (1024)
#define UART2_MSG_RECV_TIMEOUT_TICKS (3)
#define UART2_RECV_TASK_PRI (13)
#define UART2_RECV_TASK_STACK_BYTES (0x2000)
// DMA 模式需要变量内存地址对齐
#pragma DATA_ALIGN(uart2send_buf, 128);
unsigned char uart2send_buf[TLFS_UART_SEND_MAX_LEN];
#pragma DATA_ALIGN(uart2recv_buf, 128);
unsigned char uart2recv_buf[TLFS_UART_RECV_MAX_LEN];
/****************************************************************************/
/* */
/* 全局变量 */
/* */
/****************************************************************************/
EDMA3_DRV_Handle hEdma;
Uart_Params uartParams;
GIO_Handle uart2RxHandle;
GIO_Handle uart2TxHandle;
static Mailbox_Handle uart2mbx = NULL;
EDMA3_DRV_Handle edma3init(unsigned int edma3Id, EDMA3_DRV_Result *);
/*
* ======== taskFxn ========
*/
static void uart2taskFxn(UArg a0, UArg a1)
{
size_t len = 1;
while(1)
{
GIO_read(uart2RxHandle,&uart2recv_buf,&len);
Mailbox_post(uart2mbx,uart2recv_buf, BIOS_NO_WAIT);
}
}
void Uart2Init()
{
Uart_init();
uartParams = Uart_PARAMS;
uartParams.hwiNumber = UART2_HWI_NUM;
uartParams.opMode = Uart_OpMode_DMAINTERRUPT;
uartParams.rxThreshold = Uart_RxTrigLvl_1;
uartParams.softTxFifoThreshold = 1;
uartParams.baudRate = Uart_BaudRate_460_8K;
Psc_ModuleClkCtrl(Psc_DevId_0, CSL_PSC_CC0, TRUE);
Psc_ModuleClkCtrl(Psc_DevId_0, CSL_PSC_TC0, TRUE);
Psc_ModuleClkCtrl(Psc_DevId_0, CSL_PSC_TC1, TRUE);
Psc_ModuleClkCtrl(Psc_DevId_1, CSL_PSC_CC1, TRUE);
}
void hal_uart2_init(void)
{
Uart_ChanParams chanParams;
GIO_Params ioParams;
UARTPinMuxSetup(2, FALSE);
// GIO 参数初始化
GIO_Params_init(&ioParams);
EDMA3_DRV_Result edmaResult = 0;
// EDMA3 初始化
hEdma = edma3init(0, &edmaResult);
chanParams.hEdma = hEdma;
ioParams.chanParams = (Ptr)&chanParams;
// 创建通道
uart2TxHandle = GIO_create("/uart2", GIO_OUTPUT, &ioParams, NULL);
uart2RxHandle = GIO_create("/uart2",GIO_INPUT, &ioParams, NULL);
if ((NULL == uart2TxHandle) || (NULL == uart2RxHandle))
{
BIOS_exit(0);
}
Mailbox_Params mbxParams;
//创造一个邮箱实例
Mailbox_Params_init(&mbxParams);
uart2mbx = Mailbox_create(sizeof(unsigned char), UART2_MSG_CNT, &mbxParams,NULL);
Error_Block eb;
Error_init(&eb);
// 创建任务
Task_Params taskParams;
Task_Handle task;
Task_Params_init(&taskParams);
taskParams.priority = UART2_RECV_TASK_PRI;
taskParams.stackSize = UART2_RECV_TASK_STACK_BYTES;
task = Task_create(uart2taskFxn, &taskParams, &eb);
if (task == NULL) {
BIOS_exit(0);
}
}
int hal_uart2_read(unsigned char* uartBuffer, size_t *len)
{
size_t length = 0;
if(uartBuffer == NULL || len == NULL)
return -1;
while(!Mailbox_getNumPendingMsgs(uart2mbx));
while(Mailbox_getNumPendingMsgs(uart2mbx))
{
Mailbox_pend(uart2mbx,&uartBuffer[length++], UART2_MSG_RECV_TIMEOUT_TICKS);
}
if(length > 0)
{
*len= length;
return 0;
}else
return -1;
}
int hal_uart2_write(unsigned char* uartBuffer, unsigned int len)
{
size_t length = 0;
if(uartBuffer == NULL)
return -1;
length = len;
if(len <= TLFS_UART_SEND_MAX_LEN)
{
memcpy(uart2send_buf, uartBuffer, len);
}else{
return -1;
}
GIO_write(uart2TxHandle, &uart2send_buf, &length);
return 0;
}