ESP8266--学习笔记(八)串口源码分析

来源:互联网 发布:广东广播开放大学网络 编辑:程序博客网 时间:2024/06/05 17:47

我一直对ESP8266的串口传输的机制很好奇,没办法只得好好分析源码了。 
 ESP8266的中断系统是必须要了解的。我分析的源代码是分配有任务的,所以在任务函数中是无法看到中断的。我的分析如下:

这里写图片描述

代码实现如下:

串口接收中断处理函数

LOCAL voiduart0_rx_intr_handler(void *para){  uint8 uart_no = UART0;//UartDev.buff_uart_no;  if(UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST))  {    os_printf("FRM_ERR\r\n");    WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR);  }  if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST))  {    ETS_UART_INTR_DISABLE();//中断失能    system_os_post(at_recvTaskPrio, 0, 0);//向任务函数发送消息  }  else if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST))  {    ETS_UART_INTR_DISABLE();////中断失能    system_os_post(at_recvTaskPrio, 0, 0);//向任务函数发送消息  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

任务函数

void ICACHE_FLASH_ATTRat_init(void){  system_os_task(at_recvTask, at_recvTaskPrio, at_recvTaskQueue, at_recvTaskQueueLen);  system_os_task(at_procTask, at_procTaskPrio, at_procTaskQueue, at_procTaskQueueLen);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

 如此这般,当串口接收中断发生时,FIFO满了或FIFO超时了,都会使得中断向任务发送消息,从而让任务中的接收任务事件跑起来。


串口中断函数分析:

首先UART的中断寄存器有:

  • UART_INT_RAW 中断原始状态寄存器
  • UART_INT_ENA 中断使能寄存器:表⽰示当前使能的uart中断。
  • UART_INT_ST 中断状态寄存器:表⽰示当前有效的中断状态
  • UART_INT_CLR 清除中断寄存器:置对应位来清除中断状态寄存器

然后UART的一些特殊的位:

  • UART_RXFIFO_FULL_INT_ST :接收full中断位
  • UART_RXFIFO_OVF_INT_ST:接收溢出中断位
  • UART_RXFIFO_TOUT_INT_ST :接收超时中断位
  • UART_TXFIFO_EMPTY_INT_ST:发送空中断位

然后UART的寄存器操作函数:

  • READ_PERI_REG(addr) 读寄存器值的函数
  • WRITE_PERI_REG(addr, val) 写寄存器函数

代码分析 uart.c–uart0_rx_intr_handler()

if(UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(UART0)) & UART_FRM_ERR_INT_ST))  {    os_printf("FRM_ERR\r\n");    WRITE_PERI_REG(UART_INT_CLR(UART0), UART_FRM_ERR_INT_CLR);  }
  • 1
  • 2
  • 3
  • 4
  • 5

根据前面的各种各样的标识符分析

  • 首先读uart0的中断状态寄存器READ_PERI_REG(UART_INT_ST(UART0))
  • 而 UART_FRM_ERR_INT_ST 是这么定义的#define UART_FRM_ERR_INT_ST (BIT(3))
  • 然后将这两个寄存器进行“和”运算再与UART_FRM_ERR_INT_ST进行判断

总结:

 经过一系列的分析,所谓的串口接收中断函数就是:中断发生后,CPU首先查看串口中断位,然后在将查询到的值与那些特殊位进行比较,得出串口的当前状态:串口接收错误?串口接收FIFO满了?串口接收FIFO超时?…….然后根据不同的状态进行不同的操作。 
 如果加入了任务调控机制,就可以在串口发生中断的时候,给任务发送消息了。让任务进行操作。

————————————————————

下面这段代码首先分析标识符:

  • READ_PERI_REG(…):读取tx/rx 队列内当前剩余的字节数
  • UART_STATUS(…)
  • UART_RXFIFO_CNT :0x000000FF (255)
  • UART_RXFIFO_CNT_S :0
while(READ_PERI_REG(UART_STATUS(UART0)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S))  {  }
阅读全文
0 0
原创粉丝点击