MTK串口驱动开发

MTK串口驱动开发

由于最近在工作中需要使用MTK的MT6261进行移动嵌入式设备的开发,所以将MTK串口驱动开发流程贴出来分享给大家。

1.使用串口工具配置UART管脚,此处配置的是UART2打开源码目录下的\custom\drv\Drv_Tool\DrvGen.exe

DrvGen双击打开
MTK串口驱动开发_第1张图片点击Open ,打开\custom\codegen\MBLTEK61D_MOS_3232_11C_BB\codegen.dws的定制文件。点击Edit,配置UART2管脚。
MTK串口驱动开发_第2张图片完成后点击确定,并点击Save,再点击Gen Code生成硬件定制信息,生成的文件在codegen.dws的同级目录下。生成配置文件之后,使用 make c,u custom peripheral指令生成新的硬件配置关系。

2.串口代码

static DCL_HANDLE g_handle = 0;
//0 成功 -1 失败
kal_int32 m_uart_open(kal_uint32 port)
{
	DCL_HANDLE handle = 0;
	handle = DclSerPort_Open(port,(module_type)MOD_UART1_HISR+port);

	if(handle)
	{
		g_handle = handle;
		return 0;
	}
	else
	{
		g_handle = 0;
		return -1;
	}
}

void m_uart_close(kal_uint32 port)
{
	DclSerPort_Close(g_handle);
	g_handle = 0;
}


void m_uart_config(kal_uint32 port,UARTDCBStruct * UART_Config)
{  
	UART_CTRL_DCB_T data;

	if(0 == g_handle)	
	{
		return;
	}
	
    /* config the UART */
	data.u4OwenrId = (module_type)MOD_UART1_HISR+port;
	data.rUARTConfig.u4Baud = UART_Config->baud;
	data.rUARTConfig.u1DataBits = UART_Config->dataBits;
	data.rUARTConfig.u1StopBits = UART_Config->stopBits;
	data.rUARTConfig.u1Parity = UART_Config->parity;
	data.rUARTConfig.u1FlowControl = UART_Config->flowControl;
	data.rUARTConfig.ucXonChar = UART_Config->xonChar;
	data.rUARTConfig.ucXoffChar = UART_Config->xoffChar;
	data.rUARTConfig.fgDSRCheck = UART_Config->DSRCheck;

    /* open the UART port, then setup the config information. */
	DclSerialPort_Control(g_handle, SIO_CMD_SET_DCB_CONFIG,
                           (DCL_CTRL_DATA_T*)&data);
}


kal_int32 m_uart_sendbytes(kal_uint32 port,kal_uint8* pSendBuff,kal_uint16 len)
{
	kal_uint32	writelen = 0;
	UART_CTRL_CLR_BUFFER_T data_clr_buf = {0};
	UART_CTRL_PURGE_T data_purge_buf = {0};
	UART_CTRL_POWERON_T	data_power_on = {0};
	
	if(0 == g_handle)	
	{
		return -1;
	}

	data_power_on.bFlag_Poweron = KAL_TRUE;
	DclSerialPort_Control(g_handle, UART_CMD_POWER_ON,(DCL_CTRL_DATA_T*)&data_power_on);

	data_purge_buf.u4OwenrId = (module_type)MOD_UART1_HISR+port;
	data_purge_buf.dir = DCL_RX_BUF;
	DclSerialPort_Control(g_handle, SIO_CMD_PURGE,(DCL_CTRL_DATA_T*)&data_purge_buf);
	data_purge_buf.dir = DCL_TX_BUF;
	DclSerialPort_Control(g_handle, SIO_CMD_CLR_RX_BUF,(DCL_CTRL_DATA_T*)&data_purge_buf);

	data_clr_buf.u4OwenrId = (module_type)MOD_UART1_HISR+port;
	DclSerialPort_Control(g_handle, SIO_CMD_CLR_RX_BUF,(DCL_CTRL_DATA_T*)&data_clr_buf);
	DclSerialPort_Control(g_handle, SIO_CMD_CLR_RX_BUF,(DCL_CTRL_DATA_T*)&data_clr_buf);

	
	return (s32)DclSerPort_WriteData(g_handle,pSendBuff,len,&writelen,(module_type)MOD_UART1_HISR+port);
}

kal_int32 m_uart_readbytes(kal_uint32 port,kal_uint8* pRecvBuff,kal_uint16 len,kal_uint32* readlen,kal_uint32 timeout)
{  
	kal_uint32	read_count_len = 0;
	kal_uint32	read_sum_len = 0;
	DCL_STATUS status;
	kal_uint32 timestart = 0;
	kal_uint32 timecurrent = 0;
	kal_uint32 tickcurrent = 0;
	UART_CTRL_POWERON_T	data_power_on = {0};
	
	if(0 == g_handle)	
	{
		return -1;
	}

	data_power_on.bFlag_Poweron = KAL_TRUE;
	DclSerialPort_Control(g_handle, UART_CMD_POWER_ON,(DCL_CTRL_DATA_T*)&data_power_on);

	kal_get_time(&tickcurrent);
	timestart = kal_ticks_to_milli_secs(tickcurrent);

	while(1)
	{
		read_count_len = 0;
		status = DclSerPort_ReadData(g_handle,pRecvBuff + read_sum_len,len - read_sum_len,&read_count_len,(module_type)MOD_UART1_HISR+port);
		if(STATUS_OK != status)
		{
			//出现错误 直接返回退出
			break;
		}
		if(readlen)
		{
			read_sum_len += read_count_len;
		}
		if(read_sum_len >= len)
		{
			*readlen = read_sum_len;
			break;
		}

		kal_get_time(&tickcurrent);
		timecurrent = kal_ticks_to_milli_secs(tickcurrent);
		if((timecurrent - timestart)>= timeout)
		{	
			*readlen = read_sum_len;
			break;
		}	
			
	}	


	return status;
	
}

3.串口代码分析

1.串口的指令通过结构体指针最终走到Uart_Handler进行处理流程如下

MTK串口驱动开发_第3张图片结构体指针
此结构体指针指向Uart_handle中的结构体
根据配置方式

MTK串口驱动开发_第4张图片通过UART_Handler来调用底层函数
MTK串口驱动开发_第5张图片MTK串口驱动开发_第6张图片MTK串口驱动开发_第7张图片UART_Driver结构体
至此,串口流程梳理完毕。

3.remark

第一次调用DCL_xx函数的时候程序会异常死机,最后查到原因是我的MTK源码中的				  

DCL_STATUS DclSerPort_ReadData(DCL_HANDLE handle, DCL_BUFF *buff, DCL_BUFF_LEN buf_len, DCL_BUFF_LEN *returned_len, DCL_OPTIONS options)
{

UART_CTRL_GET_BYTES_T data;
 DCL_STATUS status;
data.u4OwenrId =(module_type)options;
data.u2Length = buf_len;
data.puBuffaddr = buff;
data.pustatus = NULL;	//此语句缺失导致系统重启
status = 	DclSerialPort_Control(handle,SIO_CMD_GET_BYTES, (DCL_CTRL_DATA_T*)&data);
*returned_len = data.u2RetSize;

return status;
}

4.欢迎各位补充干货分享

你可能感兴趣的:(技术分享)