Telink uart配置 DMA/NDMA

基于 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可以正常运行,不会出现卡循环的情况。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于Telink IDE的配置,可以按照以下步骤进行操作: 1. 下载和安装Telink IDE:首先,你需要从Telink官方网站下载并安装Telink IDE。它是一个集成开发环境,用于Telink芯片的开发和调试。 2. 配置目标芯片:打开Telink IDE后,你需要配置目标芯片的型号和连接方式。在IDE的菜单栏中,选择“Options”或“Preferences”(具体名称可能会有所不同),然后找到“Target”或“Device”选项。在这里,你可以选择你使用的芯片型号,并选择与电脑连接的方式(如USB连接或JTAG连接)。 3. 创建工程:在IDE中,你可以创建一个新的工程来开始你的开发项目。在IDE的菜单栏中,选择“File”->“New Project”或类似选项。然后,按照向导的指示,选择你的芯片型号、工程名称和存储路径等信息。 4. 配置编译器:Telink IDE使用GCC编译器来编译和构建项目。确保你已经正确配置了编译器路径。在IDE的菜单栏中,选择“Options”或“Preferences”,然后找到“Build Tools”或类似选项。在这里,你可以指定GCC编译器的路径。 5. 编写代码:使用Telink IDE内置的代码编辑器,你可以编写你的应用程序代码。你可以创建新的源文件、添加库文件等等。Telink IDE支持C语言和汇编语言编程。 6. 构建和调试:在完成代码编写后,你可以使用IDE提供的构建工具来编译和构建你的项目。通过选择菜单栏中的“Build”或类似选项,IDE将执行编译过程并生成可执行文件。如果需要进行调试,你可以使用IDE提供的调试功能来单步执行、设置断点等。 这些是Telink IDE的基本配置步骤,具体操作可能会因版本和开发环境而有所不同。如果你遇到问题,建议参考Telink IDE的官方文档或寻求Telink开发者社区的帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值