基于 B91 SDK 下的配置 有两种配置方式NDMA和DMA,在下列代码中演示
NDMA 串口配置
void uart0_init()
{
uart_reset(UART0);
uart_set_pin(UART0_TX_PB2, UART0_RX_PB3 );// uart tx/rx pin set
unsigned short div;
unsigned char bwpc;
uart_cal_div_and_bwpc(115200, sys_clk.pclk*1000*1000, &div, &bwpc);
uart_init(UART0, div, bwpc, UART_PARITY_NONE, UART_STOP_BIT_ONE);
//uart irq set
plic_interrupt_enable(IRQ19_UART0);
plic_set_priority(IRQ19_UART0,1); //优先级
uart_tx_irq_trig_level(UART0, 0);
uart_rx_irq_trig_level(UART0, 1);
uart_set_irq_mask(UART0, UART_RX_IRQ_MASK);
}
void uart0_irq_handler(void)
{
if(uart_get_irq_status(UART0, UART_RXBUF_IRQ_STATUS))
{
extern void uart0_recieve_irq(void);
uart0_recieve_irq();
}
}
void uart0_recieve_irq(void)
{
if(uart0_flag == UART0_RECIEVE_IDLE)
{
uart0_ndmairq_cnt = 4;//recieve packet start
}
u8* p = my_fifo_wptr(&spp_rx_fifo);
p[uart0_ndmairq_cnt] = uart_read_byte(UART0);
uart_send_byte(UART0,p[uart0_ndmairq_cnt]); //发送单字节
while(uart_tx_is_busy(UART0));
uart0_ndmairq_cnt++;
if(uart0_flag == UART0_RECIEVE_IDLE)
{
uart0_flag = UART0_RECIEVE_START;
}
uart0_ndma_tick = clock_time();
}
DMA串口配置
void uart0_init()
{
unsigned short div;
unsigned char bwpc;
uart_reset(UART0);
uart_set_pin(UART0_TX_PB2 ,UART0_RX_PB3 );// uart tx/rx pin set
uart_cal_div_and_bwpc(115200, sys_clk.pclk*1000*1000, &div, &bwpc);
//uart_set_rx_timeout(UART0, bwpc, 12, UART_BW_MUL1);
uart_init(UART0, div, bwpc, UART_PARITY_NONE, UART_STOP_BIT_ONE);
uart_clr_irq_mask(UART0, UART_RX_IRQ_MASK | UART_TX_IRQ_MASK | UART_TXDONE_MASK|UART_RXDONE_MASK);
core_interrupt_enable();
uart_set_tx_dma_config(UART0, UART_DMA_CHANNEL_TX);
uart_set_rx_dma_config(UART0, UART_DMA_CHANNEL_RX);
uart_clr_tx_done(UART0);
uart_set_irq_mask(UART0, UART_RXDONE_MASK);
uart_set_irq_mask(UART0, UART_TXDONE_MASK);
plic_interrupt_enable(IRQ19_UART0);
u8 *uart_rx_addr = (spp_rx_fifo_b + (spp_rx_fifo.wptr & (spp_rx_fifo.num-1)) * spp_rx_fifo.size);
uart_receive_dma(UART0,(unsigned char *)uart_rx_addr, (unsigned int)spp_rx_fifo.size);
extern int rx_from_uart_cb (void);
extern int tx_to_uart_cb (void);
blc_register_hci_handler(rx_from_uart_cb, tx_to_uart_cb); //注册函数
}
void uart0_irq_handler(void)
{
extern void uart0_recieve_irq(void);
uart0_recieve_irq();
}
void uart0_recieve_irq(void)
{
if(uart_get_irq_status(UART0,UART_TXDONE))
{
uart_dma_send_flag=0;
uart_clr_tx_done(UART0);
}
if(uart_get_irq_status(UART0,UART_RXDONE)) //A0-SOC can't use RX-DONE status,so this interrupt can noly used in A1-SOC.
{
/************************cll rx_irq****************************/
uart_clr_irq_status(UART0,UART_CLR_RX);
u8* w = spp_rx_fifo.p + (spp_rx_fifo.wptr & (spp_rx_fifo.num-1)) * spp_rx_fifo.size;
if(w[0]!=0)
{
my_fifo_next(&spp_rx_fifo);
u8* p = spp_rx_fifo.p + (spp_rx_fifo.wptr & (spp_rx_fifo.num-1)) * spp_rx_fifo.size;
uart_receive_dma(UART0,(unsigned char *)p, (unsigned int)spp_rx_fifo.size);
}
if((uart_get_irq_status(UART0,UART_RX_ERR)))
{
uart_clr_irq_status(UART0,UART_CLR_RX);
}
}
}
int rx_from_uart_cb (void)
{
if(my_fifo_get(&spp_rx_fifo) == 0)
{
return 0;
}
u8* p = my_fifo_get(&spp_rx_fifo);
u32 rx_len = p[0]; //usually <= 255 so 1 byte should be sufficient
if (rx_len)
{
bls_uart_handler(&p[0], rx_len+4); //控制发送位数,看着打印调就行
//bls_uart_handler(&p[4], rx_len - 4);
my_fifo_pop(&spp_rx_fifo);
}
return 0;
}
int tx_to_uart_cb (void)
{
u8 *p = my_fifo_get (&spp_tx_fifo);
if (p && !uart_dma_send_flag)
{
memcpy(&T_txdata_buf.data, p + 2, p[0]+p[1]*256);
T_txdata_buf.len = p[0]+p[1]*256 ;
if (uart_send_dma(UART0,(u8 *)(&T_txdata_buf.data),T_txdata_buf.len))
{
my_fifo_pop (&spp_tx_fifo);
uart_dma_send_flag=1;
}
}
return 0;
}
int bls_uart_handler (char *p, int n)
{
my_fifo_push_spp((unsigned char *)p,n);
return 0;
}
int my_fifo_push_spp(unsigned char *p_buf ,unsigned char len)
{
if(my_fifo_push(&spp_tx_fifo,p_buf,len)==0){
return 1;
}else{
return 0;
}
}
注1:上面代码直接复制是会报错的,有些参数没有写进来,但是在原SDK中是有这些参数的,需要仔细去看看。
注2:在B91单连接SDK中使用NDMA串口是会发生问题的,会导致程序卡在中断位置,主循环不运行,蓝牙自然也就不运行了,而使用DMA串口则不会出现该问题。
注3:在B91多连接的SDK中,NDMA可以正常运行,不会出现卡循环的情况。