g_dmaCTRL g_dmaCTRLPKT_TX;
g_dmaCTRL g_dmaCTRLPKT_RX;
uint32 DMA_Comp_Flag_Tx;
uint32 DMA_Comp_Flag_Rx;
/** @fn void scidmaInit(sciBASE_t *sci)
* @brief 初始化 SCI 和 DMA 以通过 DMA 传输 SCI 数据
* @note 此函数配置 SCI 以在 SCI TX 完成时触发 DMA 请求。
*/
void scidmaInit(sciBASE_t *sci)
{
/* 启用 DMA */
dmaEnable();
if (sci == scilinREG)
{ /* SCI2 是 LAUNCHXL2 启动板上的默认串口 */
/* 在接收数据后启用中断 */
dmaEnableInterrupt(DMA_CH0, BTC); /* DMA_CH0 是最高优先级 */
dmaEnableInterrupt(DMA_CH1, BTC); /* DMA_CH1 用于 RX */
/* 分配 DMA 请求:通道-0 与请求线-1 – TX */
/* DMA 请求 29 是 LIN(SCI2)传输 */
dmaReqAssign(DMA_CH0, 29);
/* DMA 请求 28 是 LIN(SCI2)接收 */
dmaReqAssign(DMA_CH1, 28);
}
else if (sci == sciREG)
{ /* SCI1 */
return; /* 目前不支持 SCI1 */
}
else
{
return; /* 未知寄存器 */
}
/* – 填充 dma 控制包结构 */
g_dmaCTRLPKT_TX.CHCTRL = 0; /* 通道控制 */
g_dmaCTRLPKT_TX.ELCNT = 1; /* 元素计数 */
g_dmaCTRLPKT_TX.ELDOFFSET = 0; /* 元素目的地偏移 */
g_dmaCTRLPKT_TX.ELSOFFSET = 0; /* 元素源偏移 */
g_dmaCTRLPKT_TX.FRDOFFSET = 0; /* 帧目的地偏移 */
g_dmaCTRLPKT_TX.FRSOFFSET = 0; /* 帧源偏移 */
g_dmaCTRLPKT_TX.PORTASGN = 4; /* 端口 b */
g_dmaCTRLPKT_TX.RDSIZE = ACCESS_8_BIT; /* 读取大小 */
g_dmaCTRLPKT_TX.WRSIZE = ACCESS_8_BIT; /* 写入大小 */
g_dmaCTRLPKT_TX.TTYPE = FRAME_TRANSFER; /* 传输类型 */
g_dmaCTRLPKT_TX.ADDMODERD = ADDR_INC1; /* 读取地址模式 */
g_dmaCTRLPKT_TX.ADDMODEWR = ADDR_FIXED; /* 写入地址模式 */
g_dmaCTRLPKT_TX.AUTOINIT = AUTOINIT_OFF; /* 自动初始化 */
/* – 填充 RX dma 控制包结构 */
g_dmaCTRLPKT_RX.CHCTRL = 0;
g_dmaCTRLPKT_RX.ELCNT = 1;
g_dmaCTRLPKT_RX.ELDOFFSET = 0;
g_dmaCTRLPKT_RX.ELSOFFSET = 0;
g_dmaCTRLPKT_RX.FRDOFFSET = 0;
g_dmaCTRLPKT_RX.FRSOFFSET = 0;
g_dmaCTRLPKT_RX.PORTASGN = 4;
g_dmaCTRLPKT_RX.RDSIZE = ACCESS_8_BIT;
g_dmaCTRLPKT_RX.WRSIZE = ACCESS_8_BIT;
g_dmaCTRLPKT_RX.TTYPE = FRAME_TRANSFER;
g_dmaCTRLPKT_RX.ADDMODERD = ADDR_FIXED;
g_dmaCTRLPKT_RX.ADDMODEWR = ADDR_INC1;
g_dmaCTRLPKT_RX.AUTOINIT = AUTOINIT_OFF;
/* 重置标志 */
DMA_Comp_Flag_Tx = 0x55AAD09E;
DMA_Comp_Flag_Rx = 0x55AAD09E;
/* 通道 40 – 在 HalCoGen 中启用 VIM 通道以包含 dmaBTCAInterrupt 函数 */
vimChannelMap(40, 40, &dmaBTCAInterrupt);
/* 在 SCI2 传输完成时启用 VIM DMA BTCA 中断到 CPU */
vimEnableInterrupt(40, SYS_IRQ);
/* 通道 41 – 在 HalCoGen 中启用 VIM 通道以包含 dmaBTCAInterrupt 函数 */
vimChannelMap(41, 41, &dmaBTCAInterrupt);
/* 在 SCI2 接收完成时启用 VIM DMA BTCA 中断到 CPU */
vimEnableInterrupt(41, SYS_IRQ);
} /* scidmaInit */
/** @fn void scidmaSend(char *source_address)
* @brief 初始化 SCI 和 DMA 以通过 DMA 传输 SCI 数据
* @note 此函数配置 SCI 以在 SCI TX 完成时触发 DMA 请求。
*
* 此函数配置 DMA 以单缓冲或多缓冲模式工作。
* 在单缓冲模式(0)下,DMA 在请求设置时将每个字节移动到 SCI 传输寄存器。
* 在多缓冲模式(1)下,DMA 在请求设置时将 4 个字节移动到 SCI 传输缓冲区。
*/
void scidmaSend(char *source_address)
{
#if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
uint8 dest_addr_offset = 0; /* 小端模式为 0 */
#else
uint8 dest_addr_offset = 3; /* 大端模式为 3 */
#endif
/* 等待 DMA 完成任何现有传输 */
while (DMA_Comp_Flag_Tx != 0x55AAD09E)
;
/* 将标志重置为未完成 */
DMA_Comp_Flag_Tx = ~0x55AAD09E;
/* – 填充 dma 控制包结构 */
g_dmaCTRLPKT_TX.SADD = (uint32)source_address; /* 源地址 */
if (((scilinREG->GCR1 >> 10U) & 1U) == 0U)
{ /* SCI2 多缓冲模式 */
g_dmaCTRLPKT_TX.DADD = (uint32)(&(scilinREG->TD)) + dest_addr_offset; /* 在大端设备中,目的地址需要调整 */
g_dmaCTRLPKT_TX.RDSIZE = ACCESS_8_BIT; /* 读取大小 */
g_dmaCTRLPKT_TX.WRSIZE = ACCESS_8_BIT; /* 写入大小 */
g_dmaCTRLPKT_TX.FRCNT = strlen(source_address); /* 帧计数 */
}
else
{
g_dmaCTRLPKT_TX.DADD = (uint32)(&(linREG->TDx)); /* 在大端设备中,目的地址需要调整
* 以进行字节访问。DMA 是大端主控。SCI 传输缓冲区
* 可在最低有效字节处访问。 */
g_dmaCTRLPKT_TX.RDSIZE = ACCESS_32_BIT; /* 读取大小 */
g_dmaCTRLPKT_TX.WRSIZE = ACCESS_32_BIT; /* 写入大小 */
g_dmaCTRLPKT_TX.FRCNT = strlen(source_address) / 4 + 8; /* 帧计数 */
}
/* – 设置传输的 dma 控制包 */
dmaSetCtrlPacket(DMA_CH0, g_dmaCTRLPKT_TX);
/* – 设置 dma 通道以触发硬件请求 */
dmaSetChEnable(DMA_CH0, DMA_HW);
/* 启用 TX DMA */
scilinREG->SETINT = (1 << 16);
} /* scidmaSend */
void scidmaReceive(char *dest_address, uint32 length)
{
#if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
uint8 src_addr_offset = 0; /* 小端模式为 0 */
#else
uint8 src_addr_offset = 3; /* 大端模式为 3 */
#endif
/* 等待 DMA 完成任何现有传输 */
while (DMA_Comp_Flag_Rx != 0x55AAD09E)
;
/* 将标志重置为未完成 */
DMA_Comp_Flag_Rx = ~0x55AAD09E;
/* – 填充 dma 控制包结构 */
g_dmaCTRLPKT_RX.SADD = (uint32)(&(scilinREG->RD)) + src_addr_offset; /* 源地址 */
g_dmaCTRLPKT_RX.DADD = (uint32)dest_address; /* 目的地址 */
g_dmaCTRLPKT_RX.FRCNT = length; /* 帧计数 */
/* 设置传输的 dma 控制包 */
dmaSetCtrlPacket(DMA_CH1, g_dmaCTRLPKT_RX);
/* 设置 dma 通道以触发硬件请求 */
dmaSetChEnable(DMA_CH1, DMA_HW);
/* 启用 RX DMA */
scilinREG->SETINT = (1 << 17);
}
void Update_DMA_Comp_Flag_Tx()
{
/* 设置发送完成标志 */
DMA_Comp_Flag_Tx = 0x55AAD09E;
/* 禁用 TX DMA 中断 */
scilinREG->CLEARINT = (1 << 16);
}
void Update_DMA_Comp_Flag_Rx()
{
/* 设置接收完成标志 */
DMA_Comp_Flag_Rx = 0x55AAD09E;
/* 禁用 RX DMA 中断 */
scilinREG->CLEARINT = (1 << 17);
}
/** @fn void linsci2enableMBUFF()
* @brief Switch SCI2 to multi-buffer (4 Byte) transfers
* @note This function requires scidmaInit(scilinREG) and _enable_IRQ() to be called first.
*
* In multi buffer mode (1) the DMA moves 4 Bytes to the SCI transmit buffer when the request is set.
* The DMA interconnect does not support 64bit unaligned accesses which limits transfers to a max of 4 bytes.
*/
void linsci2enableMBUFF()
{
/* Enable Multi- Buffer Mode */
scilinREG->GCR1 |= (uint32)((uint32)1U << 10U); /* Enable MBUFMODE (SCI2 Only) */
/* Set transmission length in Bytes */
scilinREG->FORMAT = (uint32)((uint32)7U << 0U) /* character length (bits) -1 */
| (uint32)((uint32)3U << 16U); /* frame length (bytes) -1 */
} /* linsci2enableMBUFF */
/** @fn void linsci2disableMBUFF()
* @brief Switch SCI2 to single byte transfers
* @note This function requires linsci2enableMBUFF() to be called first.
*
* In multi buffer mode (1) the DMA moves 4 Bytes to the SCI transmit buffer when the request is set.
* The DMA interconnect does not support 64bit unaligned accesses which limits transfers to a max of 4 bytes.
*/
void linsci2disableMBUFF()
{
/* Enable Multi- Buffer Mode */
scilinREG->GCR1 &= ~(uint32)((uint32)1U << 10U); /* Disable MBUFMODE (SCI2 Only) */
/* Set transmission length in Bytes */
scilinREG->FORMAT = (uint32)((uint32)7U << 0U) /* character length (bits) -1 */
| (uint32)((uint32)0U << 16U); /* frame length (bytes) -1 */
} /* linsci2enableMBUFF */