// ============================================================================= // 功能:字符终端直接接收函数,采用轮询方式,直接读寄存器,用于stdin初始化前 // 参数:str,发送字符串指针 // len,发送的字节数 // 返回:0,发生错误;result,发送数据长度,字节单位 // ============================================================================= char Uart_GetCharDirect(void) { u16 CR_Bak; char result; CR_Bak = PutStrDirectReg->UART_IER; //Save INT __UART_SendIntDisable(PutStrDirectReg,0); //disable send INT __UART_SendIntDisable(PutStrDirectReg,1); //disable send INT when dma while(__UART_RxHadChar(GetCharDirectReg) == false) ; result = GetCharDirectReg->UART_RHR; PutStrDirectReg->UART_IER = CR_Bak; //restore send INT return result; }
// ============================================================================= // 功能: 配置uart为DMA方式或配置为非DMA方式时,配置各寄存器, // 参数:reg,串口寄存器指针 // cmd,命令号 // Port,端口号,即串口号 // 返回: 无 // ============================================================================= void __UART_DMA_Config(tagUartReg* Reg,u32 cmd,u32 Port) { //将串口相关的寄存器reset并除能接收和发送 Reg->UART_CR = ((1<<2)|(1<<3)|(1<<5)| (1<<7)|(1<<8)); //接收发送都除能了 if(cmd == CN_UART_DMA_UNUSED)//不使用DMA { s_UART_DmaUsed[Port] = false; //关闭非dma时使用的中断,开始dma使用的uart接收中断 //发送中断只在启动发送时开启 __UART_RecvIntDisable(Reg, cn_dma_used); __UART_SendIntDisable(Reg, cn_dma_used); __UART_RecvIntEnable(Reg, cn_dma_unused); Reg->UART_PTCR = ((1<<1)|(1<<9));//disable DMA rx tx Reg->UART_CR = ((1<<4)|(1<<6));// tx rx enable } else //使用DMA { s_UART_DmaUsed[Port] = true; //关闭非dma时使用的中断,开始dma使用的uart接收中断 __UART_RecvIntEnable(Reg, cn_dma_used); __UART_RecvIntDisable(Reg, cn_dma_unused); __UART_SendIntDisable(Reg, cn_dma_unused); //配置dma参数 Reg->UART_TCR = 0; Reg->UART_TNCR = 0; Reg->UART_RCR = 0; Reg->UART_RNCR = 0; __UART_dma_recv_config(Reg,Port,1); Reg->UART_PTCR = ((1<<0)|(1<<8));//enable DMA rx tx Reg->UART_CR = ((1<<4)|(1<<6));// tx rx enable } }
// ============================================================================= // 功能:字符终端直接发送函数,采用轮询方式,直接写寄存器,用于printk,或者stdout // 没有初始化 // 参数:str,发送字符串指针 // len,发送的字节数 // 返回:0,发生错误;result,发送数据长度,字节单位 // ============================================================================= s32 Uart_PutStrDirect(const char *str,u32 len) { u32 result = 0,timeout = TxByteTime * len; u16 CR_Bak; CR_Bak = PutStrDirectReg->UART_IER; //Save INT __UART_SendIntDisable(PutStrDirectReg,0); //disable send INT __UART_SendIntDisable(PutStrDirectReg,1); //disable send INT when dma for(result=0; result < len+1; result ++) { // 超时或者发送缓冲为空时退出 while((false == __UART_TxTranEmpty(PutStrDirectReg))&& (timeout > 10)) { timeout -=10; Djy_DelayUs(10); } if( (timeout <= 10) || (result == len)) break; PutStrDirectReg->UART_THR = str[result]; } PutStrDirectReg->UART_IER = CR_Bak; //restore send INT return result; }
// ============================================================================= // 功能: 打印函数,直接写串口方式,目前主要由djy_printk独享,用于调试关键代码段 // 参数: 所需要发送的字符串,当然,前提是你提供的一定是字符串'\0'结束 // 返回: 发送的字节个数 // ============================================================================= u32 Uart_SendServiceDirectly(char *str) { u32 result=0,len,timeout=100*mS; tagUartReg *Reg; u32 BaseAddr,Port; if(!strcmp(gc_pCfgStddevName,"UART0") && (sUartInited & (0x01 << CN_UART0))) { BaseAddr = CN_UART0_BASE; Port = CN_UART0; } else if(!strcmp(gc_pCfgStddevName,"UART1")&& (sUartInited & (0x01 << CN_UART1))) { BaseAddr = CN_UART1_BASE; Port = CN_UART1; } else if(!strcmp(gc_pCfgStddevName,"USART0")&& (sUartInited & (0x01 << CN_USART0))) { BaseAddr = CN_USART0_BASE; Port = CN_USART0; } else if(!strcmp(gc_pCfgStddevName,"USART1")&& (sUartInited & (0x01 << CN_USART1))) { BaseAddr = CN_USART1_BASE; Port = CN_USART1; } else return 0; len = strlen(str); Reg = (tagUartReg *)BaseAddr; __UART_SendIntDisable(Reg,s_UART_DmaUsed[Port]); //disable send INT for(result=0; result < len; result ++) { // 超时或者发送缓冲为空时退出 while((false == __UART_TxTranEmpty(Reg))&& (timeout > 0)) { timeout--; Djy_DelayUs(1); } if(timeout == 0) break; Reg->UART_THR = str[result]; } __UART_SendIntEnable(Reg,s_UART_DmaUsed[Port]); //enable send INT return result; }
// ============================================================================= // 功能: 串口设备的控制函数,与具体的硬件寄存器设置相关 // 参数: Reg,UART的寄存器基址. // cmd,操作类型 // data,含义依cmd而定 // 返回: 无意义. // ============================================================================= ptu32_t __UART_Ctrl(tagUartReg *Reg,u32 cmd, u32 data1,u32 data2) { u8 Port; switch((u32)Reg) { case CN_UART0_BASE: Port = CN_UART0;break; case CN_UART1_BASE: Port = CN_UART1;break; case CN_USART0_BASE: Port = CN_USART0;break; case CN_USART1_BASE: Port = CN_USART1;break; default:return 0; } switch(cmd) { case CN_UART_START: __UART_RecvIntEnable(Reg,s_UART_DmaUsed[Port]); __UART_SendIntEnable(Reg,s_UART_DmaUsed[Port]); break; case CN_UART_STOP: __UART_RecvIntDisable(Reg,s_UART_DmaUsed[Port]); __UART_SendIntDisable(Reg,s_UART_DmaUsed[Port]); break; case CN_UART_SET_BAUD: //设置Baud __UART_SetBaud(Reg,data1); break; case CN_UART_RX_PAUSE: //暂停接收 __UART_RecvIntEnable(Reg,s_UART_DmaUsed[Port]); break; case CN_UART_RX_RESUME: //恢复接收 __UART_RecvIntDisable(Reg,s_UART_DmaUsed[Port]); break; case CN_UART_RECV_HARD_LEVEL: //因为UART没有FIFO,因此配置DMA接收 __UART_dma_recv_config(Reg,Port,data1); break; case CN_UART_HALF_DUPLEX_SEND: __UART_half_duplex_send(Port); break; case CN_UART_HALF_DUPLEX_RECV: __UART_half_duplex_recv(Port); break; case CN_UART_DMA_USED: case CN_UART_DMA_UNUSED: __UART_DMA_Config(Reg,cmd,Port); break; default: break; } return 0; }
// ============================================================================= // 功能: 使用中断方式效率能够大大提升软件执行效率;包括接收、发送和异常等,接收到数据 // 后,调用通用接口模块,写入软件缓冲区;发送数据时,调用通用接口模块,从软件缓 // 冲区读出数据,写入硬件发送寄存器;此外,根据芯片,可通过DMA方式发送 // 参数: 中断号. // 返回: 0. // ============================================================================= uint32_t UART_ISR(ufast_t IntLine) { static struct tagUartCB *UCB; tagUartReg *Reg; uint32_t timeout = 1000,num; uint8_t ch,*puart_dma_send_buf,*puart_dma_recv_buf; uint32_t IIR=0,Port,DmaBufLen,DmaRcvLen; switch(IntLine) { case CN_INT_LINE_UART0: Port = CN_UART0; UCB = pUartCB[Port]; Reg = (tagUartReg *)CN_UART0_BASE; DmaBufLen = UART0_DMA_BUF_LEN; DmaRcvLen = s_UART0_DmaRcvLen; puart_dma_send_buf = (uint8_t*)UART0_DmaSendBuf; puart_dma_recv_buf = (uint8_t*)UART0_DmaRecvBuf; break; case CN_INT_LINE_UART1: Port = CN_UART1; UCB = pUartCB[Port]; Reg = (tagUartReg *)CN_UART1_BASE; DmaBufLen = UART1_DMA_BUF_LEN; DmaRcvLen = &s_UART1_DmaRcvLen; puart_dma_send_buf = (uint8_t*)UART1_DmaSendBuf; puart_dma_recv_buf = (uint8_t*)UART1_DmaRecvBuf; break; case CN_INT_LINE_USART0: Port = CN_USART0; UCB = pUartCB[Port]; Reg = (tagUartReg *)CN_UART1_BASE; DmaBufLen = USART0_DMA_BUF_LEN; DmaRcvLen = &s_USART0_DmaRcvLen; puart_dma_send_buf = (uint8_t*)USART0_DmaSendBuf; puart_dma_recv_buf = (uint8_t*)USART0_DmaRecvBuf; break; case CN_INT_LINE_USART1: Port = CN_USART1; UCB = pUartCB[Port]; Reg = (tagUartReg *)CN_UART1_BASE; DmaBufLen = USART1_DMA_BUF_LEN; DmaRcvLen = &s_USART1_DmaRcvLen; puart_dma_send_buf = (uint8_t*)USART1_DmaSendBuf; puart_dma_recv_buf = (uint8_t*)USART1_DmaRecvBuf; break; default: return 0; } IIR = Reg->UART_SR; if(s_UART_DmaUsed[Port] == cn_dma_unused)//非DMA方式发送和接收 { if((IIR & (1<<0)) && (Reg->UART_IMR &(1<<0)))//rxrdy int { ch = Reg->UART_RHR; num = UART_PortWrite(UCB,&ch,1,0); if(num != 1) { UART_ErrHandle(UCB,CN_UART_BUF_OVER_ERR); } } //tx empty int if((IIR &(1<<9)) && (Reg->UART_IMR &(1<<9))) { num = UART_PortRead(UCB,&ch,1,0); while((!__UART_TxTranEmpty(Reg)) && (timeout-- > 0)); if(num != 0) Reg->UART_THR = ch; else { __UART_SendIntDisable(Reg,s_UART_DmaUsed[Port]); } } } else //DMA方式发送和接收 { if((IIR & (1<<3)) && (Reg->UART_IMR &(1<<3)))//endrx int { if(DmaRcvLen > DmaBufLen) //计算从DMA BUF中读多少数据 num = DmaBufLen; else num = DmaRcvLen; UART_PortWrite(UCB,puart_dma_recv_buf,num,0); DmaRcvLen = DmaRcvLen - num; if(DmaRcvLen > DmaBufLen) //计算下次DMA接收数据量 Reg->UART_RCR = DmaBufLen; else if(DmaRcvLen > 1) Reg->UART_RCR = DmaRcvLen; else //接收DMA最少为1 { Reg->UART_RCR = 1; DmaRcvLen = 1; } Reg->UART_RPR = (vu32)puart_dma_recv_buf; } if((IIR & (1<<11)) && (Reg->UART_IMR &(1<<11)))//txbufe int { while(!(Reg->UART_SR & (1<<9)));//wait for empty num = UART_PortRead(UCB,puart_dma_send_buf, DmaBufLen,0); if(num > 0) { Reg->UART_PTCR = (1<<9);//diable dma tx if((Reg->UART_TCR==0)&&(Reg->UART_TNCR==0)) { // num = UART_PortRead(UCB,puart_dma_send_buf, // DmaBufLen,0); Reg->UART_TPR = (uint32_t)puart_dma_send_buf; Reg->UART_TCR = num; } Reg->UART_PTCR = (1<<8);//enable dma tx } else { //是否需禁止 dma tx int while(!__UART_TxTranEmpty(Reg)); __UART_SendIntDisable(Reg,s_UART_DmaUsed[Port]); } } } if(IIR &(0xE0)) //其他中断 { UART_ErrHandle(UCB,CN_UART_HARD_COMM_ERR); } return 0; }
// ============================================================================= // 功能: 这个是直接写串口函数,不会经过事件弹出 // 参数: Reg,UART的寄存器基址. // send_buf,被发送的缓冲数据 // len,发送的数据字节数 // timeout,超时时间,微秒 // 返回: 发送的个数 // ============================================================================= u32 __UART_SendDirectly(tagUartReg* Reg,u8 *send_buf,u32 len,u32 timeout) { u32 result,Port; switch((u32)Reg) { //UART0和UART1的FIFO深度为8,而其他的为1 case CN_UART0_BASE:Port = CN_UART0; break; case CN_UART1_BASE:Port = CN_UART1;break; case CN_USART0_BASE:Port = CN_USART0;break; case CN_USART1_BASE:Port = CN_USART1; break; default:return 0; } __UART_SendIntDisable(Reg,s_UART_DmaUsed[Port]); // __UART_half_duplex_send(Port);//硬件使能发送 if(s_UART_DmaUsed[Port] == false) { for(result=0; result < len; result ++) { while((0 == __UART_TxTranEmpty(Reg)) && (timeout > 0))//超时或者发送缓冲为空时退出 { timeout--; Djy_DelayUs(1); } if(timeout == 0) break; Reg->UART_THR = send_buf[result]; } // //等待发送完再将485通信转为接收 // while((0 == __UART_TxTranEmpty(Reg)) // && (timeout > 0))//超时或者发送缓冲为空时退出 // { // timeout--; // Djy_DelayUs(1); // } // if(timeout == 0) // result = 0; } else { Reg->UART_PTCR = (1<<9);//disable dma send first if((Reg->UART_TCR==0)&&(Reg->UART_TNCR==0)) { Reg->UART_TPR = (uint32_t)send_buf; Reg->UART_TCR = len; Reg->UART_PTCR = (1<<8);//dma tx enbale } else result = 0; //直接发送方式,采用阻塞的DMA发送 while((!__UART_TxTranEmpty(Reg)) && (timeout > 0)) { timeout--; Djy_DelayUs(1); } if(timeout == 0) result = 0; } __UART_SendIntEnable(Reg,s_UART_DmaUsed[Port]); // __UART_half_duplex_recv(Port);//硬件使能接收 return result; }