当前位置: 首页 > 工具软件 > Gio > 使用案例 >

基于SYSBIOS GIO接口的uart通信DMA模式

曾景龙
2023-12-01

基于SYSBIOS GIO接口的uart通信DMA模式(不定长接收)

硬件: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;
}


 类似资料: