67. UART

67.1. 概述

  • 主要特征功能

    • 主要介绍先楫的uart外设的主要驱动接口说明和调用方法。更多内容请参考 hpm_uart_drv.h 的API说明以及相关用户手册。

    • 支持5到9位数据位,支持地址匹配。可参考 uart_9bit 例子。 9bit数据位具体支持参考每个SOC的 hpm_soc_ip_feature.hHPM_IP_FEATURE_UART_9BIT_MODE 宏定义

    • 支持DMA数据传输。可参考 uart_dma 例子

    • 支持硬件RX空闲以及TX空间检测。可参考 uart_hardware_rx_idle 例子。具体支持参考每个SOC的 hpm_soc_ip_feature.hHPM_IP_FEATURE_UART_RX_IDLE_DETECT 宏定义

    • 支持各类中断。可参考 uart_irq 例子

    • 支持接收各类错误检测,比如奇偶校验错误, FIFO溢出等。可参考 uart_rx_line_status 例子

    • 可配置停止位:1位,1.5位,2位。

    • 可配置奇偶校验位:无,奇校验,偶校验。

    • 可配置波特率。

    • 支持硬件流控

    • 接收和发送内置最大32字节的硬件FIFO缓存,具体深度可参考每个SOC的 hpm_soc_feature.hUART_SOC_FIFO_SIZE 宏定义 或者使用 hpm_uart_drv.h 中的 uart_intr_tx_slot_avail API接口获取。

67.2. uart初始化

  • 需要确保UART的时钟源已经开启,并且初始化了相关UART外设引脚。

    • 可使用`clock_add_to_group` 函数用于将UART时钟源添加到时钟组中,从而确保UART时钟源已经开启。

  • 相关枚举值介绍:

    • parity_setting_t 枚举用于配置UART奇偶校验类型,具体内容如下:

      typedef enum parity {
      
          /**< 无校验 */
          parity_none = 0,
      
          /**< 奇校验 */
          parity_odd,
      
          /**< 偶校验 */
          parity_even,
      
          /**< 校验位固定为1 */
          parity_always_1,
      
          /**< 校验位固定为0 */
          parity_always_0,
      
      } parity_setting_t;
      
    • num_of_stop_bits_t 枚举用于配置停止位长度,具体内容如下:

      typedef enum num_of_stop_bits {
      
          /**< 1位停止位 */
          stop_bits_1 = 0,
      
          /**< 1.5位停止位 */
          stop_bits_1_5,
      
          /**< 2位停止位 */
          stop_bits_2,
      
      } num_of_stop_bits_t;
      
    • word_length_t 枚举用于配置数据位长度,具体内容如下:

      typedef enum word_length {
      
          /**< 5位数据位 */
          word_length_5_bits = 0,
      
          /**< 6位数据位 */
          word_length_6_bits,
      
          /**< 7位数据位 */
          word_length_7_bits,
      
          /**< 8位数据位 */
          word_length_8_bits,
      
      } word_length_t;
      
    • uart_rxline_idle_cond_t 枚举用于配置UART RX线以及TX线空闲检测条件,具体内容如下:

      • 仅支持在当前SOC支持RX Idle检测的情况下使用,具体支持参考每个SOC的 hpm_soc_ip_feature.hHPM_IP_FEATURE_UART_RX_IDLE_DETECT 宏定义

      typedef enum hpm_uart_rxline_idle_cond {
      
          /**< 当RX线保持高电平的持续时间超过阈值时视为空闲 */
          uart_rxline_idle_cond_rxline_logic_one = 0,
      
          /**< 当接收状态机处于空闲状态的持续时间超过阈值时视为空闲 */
          uart_rxline_idle_cond_state_machine_idle = 1
      
      } uart_rxline_idle_cond_t;
      
  • 相关结构体介绍:

    • uart_modem_config_t 结构体用于配置uart的硬件流控相关参数, 具体内容如下:

      typedef struct uart_modem_config {
      
          /**< 自动流控制使能标志 */
          bool auto_flow_ctrl_en;
      
          /**< 回环模式使能标志 */
          bool loop_back_en;
      
          /**< 设置 RTS 信号电平为高标志 */
          bool set_rts_high;
      } uart_modem_config_t;
      
    • uart_rxline_idle_config_t 结构体用于配置UART RX和TX线空闲检测参数,具体内容如下:

      • 仅支持在当前SOC支持RX Idle检测的情况下使用,具体支持参考每个SOC的 hpm_soc_ip_feature.hHPM_IP_FEATURE_UART_RX_IDLE_DETECT 宏定义

      typedef struct hpm_uart_rxline_idle_detect_config {
      
          /**< RX或者TX线空闲检测使能标志 */
          bool detect_enable;
      
          /**< RX线或者TX线空闲检测中断使能标志 */
          bool detect_irq_enable;
      
          /**< RX线或者TX线空闲检测条件 */
          uart_rxline_idle_cond_t idle_cond;
      
          /**< RX线或者TX空闲检测阈值(以bit为单位) */
          uint8_t threshold;
      
      } uart_rxline_idle_config_t;
      
    • uart_config_t 结构体用于配置uart的相关参数, 具体内容如下:

      typedef struct hpm_uart_config {
          /**< uart时钟源频率(Hz) */
          uint32_t src_freq_in_hz;
      
          /**< 波特率 */
          uint32_t baudrate;
      
          /**< 停止位 */
          uint8_t num_of_stop_bits;
      
          /**< 数据位 */
          uint8_t word_length;
      
          /**< 奇偶校验 */
          uint8_t parity;/**< 奇偶校验 */
      
          /**< 发送FIFO触发中断或者DMA阈值 */
          uint8_t tx_fifo_level;
      
          /**< 接收FIFO触发中断或者DMA阈值 */
          uint8_t rx_fifo_level;
      
          /**< DMA使能标志 */
          bool dma_enable;/**< DMA使能标志 */
      
          /**< FIFO使能标志 */
          bool fifo_enable;
      
          /**< 硬件流控配置 */
          uart_modem_config_t modem_config;
      
          /**< 如果当前SOC支持RX Idle检测 */
      #if defined(HPM_IP_FEATURE_UART_RX_IDLE_DETECT) && (HPM_IP_FEATURE_UART_RX_IDLE_DETECT == 1)
          /**< 接收空闲配置 */
          uart_rxline_idle_config_t  rxidle_config;
      #endif
      
        /**< 如果当前SOC支持TX Idle检测 */
      #if defined(HPM_IP_FEATURE_UART_TX_IDLE_DETECT) && (HPM_IP_FEATURE_UART_TX_IDLE_DETECT == 1)
          /**< 发送空闲配置 */
          uart_rxline_idle_config_t  txidle_config;
      #endif
      
      /**< 如果当前SOC支持RX使能 */
      #if defined(HPM_IP_FEATURE_UART_RX_EN) && (HPM_IP_FEATURE_UART_RX_EN == 1)
          /**< 此位是用来防止RX引脚跳动导致的错误接收。在上电启动的时候后默认会把RX信号强制为高电平,在初始化的时候需要把该位置位把RX输入为正常状态 */
          bool rx_enable;
      #endif
      } uart_config_t;
      
      • fifo_enable: 用于配置uart是否使用FIFO。如果为true,则使用FIFO模式,这时候RBR/THR寄存器作为RX/TX FIFO使用;如果为flase,则为缓冲模式,RBR/THR寄存器作为单字节缓冲区使用。开启有效数据 uart_intr_id_rx_data_avail 中断时,FIFO模式下,当FIFO中数据达到阈值时会触发中断,缓冲模式下,当RBR/THR寄存器中有数据时会触发中断。

      • dma_enable: 用于配置uart是否使用DMA。如果为true,则使能uart的DMA模式,当FIFO中的数据达到阈值时会触发请求DMA。

      • tx_fifo_level: 用于配置uart发送FIFO触发中断或者DMA阈值。阈值设置可参考 uart_fifo_trg_lvl_t 枚举。有两个bit宽度方式的FIFO阈值

        • 2bit位宽的FIFO阈值,范围为0-3,当FIFO小于阈值时,会触发中断或者DMA请求。表示的FIFO阈值是:

          • 发送FIFO阈值

            枚举定义

            16字节的FIFO深度

            32字节的FIFO深度

            uart_tx_fifo_trg_not_full

            不为满

            不为满

            uart_tx_fifo_trg_lt_three_quarters

            小于12字节

            小于24字节

            uart_tx_fifo_trg_lt_half

            小于8字节

            小于16字节

            uart_tx_fifo_trg_lt_one_quarter

            小于4字节

            小于8字节

          • 举例:

            • tx_fifo_level = uart_tx_fifo_trg_lt_half, 在16字节FIFO深度的SOC下,发送FIFO深度小于8字节时,会触发一次DMA请求。

        • 4bit位宽的FIFO阈值,范围为0-31,表示的FIFO阈值是:1到32字节的FIFO阈值, 当FIFO小于等于阈值时,会触发中断或者DMA请求。该部分定义只能支持的SOC是有在 hpm_soc_ip_feature.h 定义 HPM_IP_FEATURE_UART_FINE_FIFO_THRLD 宏定义。

          • 举例:

            • tx_fifo_level = 15, 在32字节FIFO深度的SOC下,发送FIFO深度小于等于15字节时,会触发一次DMA请求。

      • rx_fifo_level: 用于配置uart接收FIFO触发中断或者DMA阈值。阈值设置可参考 uart_fifo_trg_lvl_t 枚举。

        • 2bit位宽的FIFO阈值,范围为0-3,当FIFO大于阈值时,会触发中断或者DMA请求。表示的FIFO阈值是:

          • 接收FIFO阈值

            枚举定义

            16字节的FIFO深度

            32字节的FIFO深度

            uart_rx_fifo_trg_not_empty

            不为空

            不为空

            uart_rx_fifo_trg_gt_one_quarter

            大于3字节

            大于7字节

            uart_rx_fifo_trg_gt_half

            大于7字节

            大于15字节

            uart_rx_fifo_trg_gt_three_quarters

            大于13字节

            大于27字节

          • 举例:

            • rx_fifo_level = uart_rx_fifo_trg_gt_one_quarter, 在16字节FIFO深度的SOC下,接收FIFO深度大于3字节时,会触发一次DMA请求。

        • 4bit位宽的FIFO阈值,范围为0-31,表示的FIFO阈值是:1到32字节的FIFO阈值,当FIFO大于等于阈值时,会触发中断或者DMA请求。该部分定义只能支持的SOC是有在 hpm_soc_ip_feature.h 定义 HPM_IP_FEATURE_UART_FINE_FIFO_THRLD 宏定义。

          • 举例:

            • rx_fifo_level = 27, 在32字节FIFO深度的SOC下,接收FIFO深度大于等于27字节时,会触发一次DMA请求。

      • rxidle_config: 用于配置uart接收空闲检测参数。该参数仅在当前SOC支持RX Idle检测的情况下使用,具体支持参考每个SOC的 hpm_soc_ip_feature.hHPM_IP_FEATURE_UART_RX_IDLE_DETECT 宏定义。

        • detect_enable: 用于配置uart接收空闲检测使能标志。如果为true,则使能uart的接收空闲检测。

        • detect_irq_enable: 用于配置uart接收空闲检测中断使能标志。如果为true,则使能uart的接收空闲检测中断。

        • idle_cond: 用于配置uart接收空闲检测条件。可以选择是当RX线保持高电平的持续时间超过阈值时视为空闲,或者当接收状态机处于空闲状态的持续时间超过阈值时视为空闲。

        • threshold: 用于配置uart接收空闲检测阈值。按bit单位计算。

      • txidle_config: 用于配置uart发送空闲检测参数。该参数仅在当前SOC支持TX Idle检测的情况下使用,具体支持参考每个SOC的 hpm_soc_ip_feature.hHPM_IP_FEATURE_UART_TX_IDLE_DETECT 宏定义。参数与 rxidle_config 相同。

  • 初始化API:

    • uart_default_config 函数用于配置uart的默认缺省参数,建议在uart进行初始化之前调用。具体内容如下:

      void uart_default_config(UART_Type *ptr, uart_config_t *config);
      
      • 参数说明:

        参数名

        类型

        描述

        ptr

        UART_Type *

        指向UART控制器基地址的指针

        config

        uart_config_t *

        指向UART配置结构体的指针,包含波特率/数据位/停止位等参数

      • 默认参数值是:波特率为115200,数据位为8位,停止位为1位,无奇偶校验,使能FIFO,关闭DMA, 对于支持接收和发送空闲的soc, 使能接收空闲检测,关闭发送空闲检测。

    hpm_stat_t uart_init(UART_Type *ptr, uart_config_t *config);
    
    • 参数说明:

      参数名

      类型

      描述

      ptr

      UART_Type *

      指向UART控制器基地址的指针

      config

      uart_config_t *

      指向UART配置结构体的指针,包含波特率/数据位/停止位等参数

    • 返回值:

      返回值

      描述

      status_success

      初始化成功

      status_uart_no_suitable_baudrate_parameter_found

      未找到合适的波特率参数

      status_invalid_argument

      无效的参数

    • 注意

      1. 调用前需确保时钟源已正确配置

      2. config参数中的波特率/数据位等参数需在有效范围内

      3. 需根据具体SOC特性启用相关功能宏

    • 示例:

      • 使用默认配置初始化UART0,波特率为11520,0数据位为8位,停止位为1位,无奇偶校验。

        void uart_init_sample(void)
        {
            uart_config_t config;
            uart_default_config(HPM_UART0, &config);
            config.src_freq_in_hz = clock_get_frequency(clock_uart0);
            config.baudrate = 115200;
            hpm_stat_t status = uart_init(HPM_UART0, &config);
            if (status != status_success) {
                printf("UART初始化失败\n");
            }
        }
        

67.3. uart发送

  • 支持FIFO发送以及DMA发送

67.3.1. 发送

  • 可以使用轮询方式进行FIFO发送,也可以使用中断方式进行FIFO发送。

  • 使用中断方式需要打开plic控制器对应的UART中断,使用 intc_m_enable_irq API接口打开UART中断。

  • 使用中断方式如果设置中断的优先级,使用 intc_m_enable_irq_with_priority API接口配置UART中断的优先级。

67.3.1.1. 轮询阻塞方式发送

  • 单字节发送API,

    hpm_stat_t uart_send_byte(UART_Type *ptr, uint8_t c);
    
    • 参数说明:

      参数名

      类型

      描述

      ptr

      UART_Type *

      指向UART控制器基地址的指针

      data

      uint8_t

      要发送的数据

    • 返回值:

      返回值

      描述

      status_success

      发送成功

      status_timeout

      发送超时

    • 注意:该API接口会阻塞等待FIFO发送完成。

    • 示例:

      void send_data_sample(void)
      {
          uint8_t data = 0x12;
          hpm_stat_t status = uart_send_byte(uart0, data);
          if (status == status_success) {
              printf("send data success\n");
          } else {
              printf("send data failed\n");
          }
      }
      
  • 多字节发送API,

    hpm_stat_t uart_send_data(UART_Type *ptr, uint8_t *source, uint32_t size_in_byte);
    
    • 参数说明:

      参数名

      类型

      描述

      ptr

      UART_Type *

      指向UART控制器基地址的指针

      source

      uint8_t *

      要发送的数据

      size_in_byte

      uint32_t

      要发送的数据长度

    • 返回值:

      返回值

      描述

      status_success

      发送成功

      status_timeout

      发送超时

    • 注意:该API接口会阻塞等待FIFO发送完成。

    • 示例:

    void send_data_sample(void)
    {
        uint8_t data[] = {0x12, 0x34, 0x56, 0x78};
        hpm_stat_t status = uart_send_data(uart0, data, sizeof(data));
        if (status == status_success) {
            printf("send data success\n");
        } else {
            printf("send data failed\n");
        }
    }
    

67.3.1.2. 中断方式发送

  • 先楫uart具有高达32字节的发送FIFO硬件缓存,可以开启发送空闲中断,在一开始发送数据的时候,数据塞入一部分到FIFO,然后开启发送空闲中断,当FIFO发送完成之后,会触发发送空闲中断,此时可以继续往FIFO塞入数据,直到FIFO满。

  • 单字节发送API,此API是将数据写入FIFO,不会等待发送完成立即返回。

    void uart_write_byte(UART_Type *ptr, uint8_t c)
    
    • 参数说明:

      参数名

      类型

      描述

      ptr

      UART_Type *

      指向UART控制器基地址的指针

      data

      uint8_t

      要发送的数据

    • 示例:

    #define UART_TX_SEND_SIZE  100
    uint8_t tx_buffer[UART_TX_SEND_SIZE];
    uint32_t tx_buffer_index = 0;
    uint8_t tx_fifo_size = 0;
    
    /* 中断处理函数 */
    void uart0_isr(void)
    {
        uint8_t irq_id = uart_get_irq_id(TEST_UART);
        if (irq_id & uart_intr_id_tx_slot_avail) {
    
            /* 关闭发送FIFO空中断 */
            uart_disable_irq(HPM_UART0, uart_intr_tx_slot_avail);
            /* 继续往FIFO塞入数据 */
            send_size = (tx_fifo_size <= (UART_TX_SEND_SIZE - tx_buffer_index)) ? tx_fifo_size : (UART_TX_SEND_SIZE - tx_buffer_index);
            while (send_size--) {
                uart_write_byte(HPM_UART0, tx_buffer[tx_buffer_index]);
                tx_buffer_index++;
            }
            if (tx_buffer_index < UART_TX_SEND_SIZE) {
                /* 还有数据需要发送,继续开启发送FIFO空中断 */
                uart_enable_irq(HPM_UART0, uart_intr_tx_slot_avail);
            }
        }
    }
    
    void send_data_sample(void)
    {
        uint8_t send_size = 0;
        /* 关闭发送FIFO空中断 */
        uart_disable_irq(HPM_UART0, uart_intr_tx_slot_avail);
        /* 获取FIFO大小 */
        tx_fifo_size = uart_get_fifo_size(HPM_UART0, uart_intr_tx_slot_avail);
    
        send_size = (tx_fifo_size <= UART_TX_SEND_SIZE) ? tx_fifo_size : UART_TX_SEND_SIZE;
    
        /* 往FIFO塞入数据 */
        while (tx_buffer_index < send_size) {
            uart_write_byte(HPM_UART0, tx_buffer[tx_buffer_index]);
            tx_buffer_index++;
        }
    
        /* 开启发送FIFO空中断 */
        uart_enable_irq(HPM_UART0, uart_intr_tx_slot_avail);
    }
    
    • 注意uart_intr_tx_slot_avail 中断指的是发送FIFO缓存为空中断,并不代表数据已经移位到发送移位寄存器。如果需要知道实际数据已经移位发送了,可以使用 uart_enable_rxline_idle_detection API开启使用发送空闲中断。

67.3.1.3. DMA方式发送

67.4. uart接收

  • 支持FIFO接收以及DMA接收

67.4.1. 接收

  • 可以使用轮询方式进行FIFO接收,也可以使用中断方式进行FIFO接收。

  • 使用中断方式需要打开plic控制器对应的UART中断,使用 intc_m_enable_irq API接口打开UART中断。

  • 使用中断方式如果设置中断的优先级,使用 intc_m_enable_irq_with_priority API接口配置UART中断的优先级。

67.4.1.1. 轮询阻塞方式接收

  • 单字节接收API,

    hpm_stat_t uart_receive_byte(UART_Type *ptr, uint8_t *byte);
    
    • 参数说明:

      参数名

      类型

      描述

      ptr

      UART_Type *

      指向UART控制器基地址的指针

      byte

      uint8_t *

      接收的数据指针

    • 返回值:

      返回值

      描述

      status_success

      接收成功

      status_timeout

      接收超时

    • 注意:该API接口会阻塞等待FIFO接收完成。

    • 示例:

    void receive_data_sample(void)
    {
        uint8_t data = 0;
        hpm_stat_t status = uart_receive_byte(uart0, &data);
        if (status == status_success) {
            printf("receive data success, data = 0x%x\n", data);
        } else {
            printf("receive data failed\n");
        }
    }
    
  • 多字节接收API,

    hpm_stat_t uart_receive_data(UART_Type *ptr, uint8_t *source, uint32_t size_in_byte);
    
    • 参数说明:

      参数名

      类型

      描述

      ptr

      UART_Type *

      指向UART控制器基地址的指针

      source

      uint8_t *

      接收的数据指针

      size_in_byte

      uint32_t

      要接收的数据长度

    • 返回值:

      返回值

      描述

      status_success

      接收成功

      status_fail

      接收失败

    • 注意:该API接口会阻塞等待FIFO接收完成。

    • 示例:

    void receive_data_sample(void)
    {
        uint8_t data[100];
        hpm_stat_t status = uart_receive_data(uart0, data, sizeof(data));
        if (status == status_success) {
            printf("receive data success\n");
        } else {
            printf("receive data failed\n");
        }
    }
    

67.4.1.2. 中断方式接收

  • 先楫uart具有高达32字节的接收FIFO硬件缓存,可以开启接收有效数据和超时中断,设置接收FIFO阈值,当FIFO中有数据时,会触发接收有效数据中断,当没有字符从接收 FIFO 中被移出或移入,并且在最后四个字符时间内接收 FIFO 中至少有一个字符这时候会触发FIFO超时中断。

  • 单字节接收API:此API是从FIFO中读取数据,不会等待接收完成立即返回。

    uint8_t uart_read_byte(UART_Type *ptr);
    
    • 参数说明:

      参数名

      类型

      描述

      ptr

      UART_Type *

      指向UART控制器基地址的指针

    • 返回值:

      返回值

      描述

      接收到的数据

      接收到的数据

    • 示例: 可参考 uart_rx_timeout 例子

67.4.1.3. DMA方式接收

67.5. 硬件自动流控

  • 支持CTS和RTS硬件自动流控

  • 结构体说明:

        /* UART modem配置结构体 */
    
        typedef struct uart_modem_config {
    
        /* 自动流控使能 */
        bool auto_flow_ctrl_en;
    
        /* 内部RX TX loopback使能 */
        bool loop_back_en;
    
        /* 使能RTS */
        bool set_rts_high;
    } uart_modem_config_t;
    
    • 注意

      • 不需要loopback功能,可以把 loop_back_en 设置为false

      • 只要`auto_flow_ctrl_en` 设置为true,就会使能硬件CTS硬件流控

      • 如果只需要使能CTS,可以把 set_rts_high 设置为true,auto_flow_ctrl_en 设置为true

      • 如果需要同时使能CTS和RTS,可以把 set_rts_high 设置为false,auto_flow_ctrl_en 设置为true

  • 配置API说明:

    • 使能硬件自动流控

      void uart_modem_config(UART_Type *ptr, uart_modem_config_t *config);
      
    • 参数说明:

      参数名

      类型

      描述

      ptr

      UART_Type *

      指向UART控制器基地址的指针

      config

      uart_modem_config_t *

      指向uart modem结构体指针,包含自动流控使能,内部RX TX loopback使能,使能RTS等参数。

    • 举例:使能RTS和CTS硬件流控,关闭loopback功能

      void uart_modem_config_sample(void)
      {
          uart_modem_config_t config;
          config.auto_flow_ctrl_en = true;
          config.loop_back_en = false;
          config.set_rts_high = false;
          uart_modem_config(HPM_UART0, &config);
      }
      

67.5.1. CTS硬件流控

  • 如果需要在中断中判断CTS电平状态,可以开启uart modem状态中断,然后在中断中获取CTS电平状态。

    • 注意

      • 使用中断方式必须把硬件流控关闭,也就是 uart_modem_config_tauto_flow_ctrl_en 成员变量设置为false。

      • 如果开启硬件流控,uart modem中断即使使能也不会被触发,可以使用 uart_get_modem_status API接口获取CTS电平状态。

    • 举例:使用中断方式判断CTS电平状态

      SDK_DECLARE_EXT_ISR_M(IRQn_UART0, uart_isr)
      
      void uart_isr(void)
      {
          uint32_t irq_id = uart_get_irq_id(HPM_UART0);
          uint8_t cts_sta;
          if (irq_id == uart_intr_id_modem_stat) {
              /* 读取MSR清零中断标志 */
              cts_sta = (uart_get_modem_status(HPM_UART0) & UART_MSR_DCTS_MASK) >> UART_MSR_DCTS_SHIFT;
              printf("CTS 0x%02x\r\n", cts_sta);
          }
      }
      
      void uart_modem_config_sample(void)
      {
          uart_enable_irq(HPM_UART0, uart_intr_modem_stat);
          intc_m_enable_irq_with_priority(IRQn_UART0, 2);
          uart_modem_config_t config;
          config.auto_flow_ctrl_en = false;
          config.loop_back_en = false;
          uart_modem_config(HPM_UART0, &config);
      }
      

67.5.2. 中断

  • 需要打开plic控制器对应的UART中断,使用 intc_m_enable_irq API接口打开UART中断。

  • 需要在plic控制器中配置UART中断的优先级,使用 intc_m_enable_irq_with_priority API接口配置UART中断的优先级。

  • 每次对应的中断事件发生,可以在中断处理函数中调用 uart_get_irq_id API接口获取中断ID,比如相关中断使能为 uart_intr_rx_data_avail_or_timeout ,则调用 uart_get_irq_id 获取中断ID是否为 uart_intr_id_rx_data_avail

  • UART外设支持以下中断,可以从 uart_intr_enable 枚举类型中查看。

    typedef enum uart_intr_enable {
        uart_intr_rx_data_avail_or_timeout = UART_IER_ERBI_MASK,   /* 接收到的有效数据达到FIFO阈值或FIFO超时中断 */
        uart_intr_tx_slot_avail = UART_IER_ETHEI_MASK,             /* 发送FIFO为空中断 */
        uart_intr_rx_line_stat = UART_IER_ELSI_MASK,               /* 接收线路状态中断 */
        uart_intr_modem_stat = UART_IER_EMSI_MASK,                 /* 流控状态中断 */
    
        /* 如果当前的SOC支持串口空闲中断 */
    #if defined(HPM_IP_FEATURE_UART_RX_IDLE_DETECT) && (HPM_IP_FEATURE_UART_RX_IDLE_DETECT == 1)
        uart_intr_rx_line_idle = UART_IER_ERXIDLE_MASK,           /* 接收空闲中断 */
    #endif
        /* 如果当前的SOC支持串口空闲中断 */
    #if defined(HPM_IP_FEATURE_UART_TX_IDLE_DETECT) && (HPM_IP_FEATURE_UART_TX_IDLE_DETECT == 1)
        uart_intr_tx_line_idle = UART_IER_ETXIDLE_MASK,           /* 发送空闲中断 */
    #endif
    
        /* 如果当前SOC支持接收地址匹配功能 */
    #if defined(HPM_IP_FEATURE_UART_ADDR_MATCH) && (HPM_IP_FEATURE_UART_ADDR_MATCH == 1)
        uart_intr_addr_match = UART_IER_EADDRM_MASK,                   /*  接收地址匹配中断 */
        uart_intr_addr_match_and_rxidle = UART_IER_EADDRM_IDLE_MASK,   /*  接收地址匹配和接收空闲中断 */
        uart_intr_addr_datalost = UART_IER_EDATLOST_MASK,              /*  接收地址匹配数据丢失中断 */
    #endif
    
    /*  如果当前SOC支持接收状态检测 */
    #if defined(HPM_IP_FEATURE_UART_RX_LINE_ERROR_DETECT) && (HPM_IP_FEATURE_UART_RX_LINE_ERROR_DETECT == 1)
        uart_intr_errf = UART_IER_LSR_ERRF_IRQ_EN_MASK,               /*  接收状态错误中断 */
        uart_intr_break_err = UART_IER_LSR_BREAK_IRQ_EN_MASK,         /*  传输打断中断 */
        uart_intr_framing_err = UART_IER_LSR_FRAMING_IRQ_EN_MASK,     /*  帧格式错误中断 */
        uart_intr_parity_err = UART_IER_LSR_PARITY_IRQ_EN_MASK,       /*  奇偶校验错误中断 */
        uart_intr_overrun = UART_IER_LSR_OVERRUN_IRQ_EN_MASK,         /*  接收数据溢出中断 */
    #endif
    } uart_intr_enable_t;
    
  • uart中断状态枚举定义

    typedef enum uart_intr_id {
        uart_intr_id_modem_stat = 0x0,      /*  MODEM状态中断 */
        uart_intr_id_tx_slot_avail = 0x2,   /*  发送FIFO为空中断 ,不代表发送移位寄存器移位完成。*/
        uart_intr_id_rx_data_avail = 0x4,   /*  接收FIFO数据可用中断 */
        uart_intr_id_rx_line_stat = 0x6,    /*  接收线路状态中断 */
        uart_intr_id_rx_timeout = 0xc,      /*  接收FIFO数据超时中断 */
    } uart_intr_id_t;
    
    • uart_intr_rx_data_avail_or_timeout

      • 中断触发条件: 如果使能FIFO,当接收到的数据达到FIFO阈值时就会触发,当没有字符从接收 FIFO 中被移出或移入,并且在最后四个字符时间内接收 FIFO 中至少有一个字节就会发生超时触发。

      • 中断标志清零:使用 uart_read_byte API 读取FIFO数据清零。 清零 uart_intr_id_rx_data_avail 状态,在FIFO模式下需要读取FIFO数据直到剩余数据小于FIFO阈值。

    • uart_intr_tx_slot_avail

      • 中断触发条件:发送FIFO为空时会触发。

      • 中断标志清零:使用 uart_write_byte API 写入FIFO数据。

    • uart_intr_rx_line_stat

      • 中断触发条件:接收到奇偶校验错误、帧错误、溢出错误、超时错误等。

      • 中断标志清零:使用 uart_get_status API 清零,该API也可以作为串口接收状态查询接口。

    • uart_intr_modem_stat

      • 参考 CTS硬件流控 章节

    • uart_intr_rx_line_idle

      • 中断触发条件:接收线路空闲时触发

      • 中断标志清零:使用 uart_clear_rxline_idle_flag API 清零。

      • 注意 仅支持在当前SOC支持RX Idle检测的情况下使用,具体支持参考每个SOC的 hpm_soc_ip_feature.hHPM_IP_FEATURE_UART_RX_IDLE_DETECT 宏定义

    • uart_intr_tx_line_idle

      • 中断触发条件:发送线路空闲时触发

      • 中断标志清零:使用 uart_clear_txline_idle_flag API 清零。

      • 注意 仅支持在当前SOC支持TX Idle检测的情况下使用,具体支持参考每个SOC的 hpm_soc_ip_feature.hHPM_IP_FEATURE_UART_TX_IDLE_DETECT 宏定义

    • uart_intr_addr_match

      • 中断触发条件:当收到的第一个字节数据与配置的Address匹配时触发。在中断函数使用 uart_is_addr_match API判断是否触发。

      • 中断标志清零:使用 uart_clear_addr_match_flag API 清零。

      • 注意 具体支持参考每个SOC的 hpm_soc_ip_feature.hHPM_IP_FEATURE_UART_ADDR_MATCH 宏定义

    • uart_intr_addr_match_and_rxidle

      • 中断触发条件:当收到的第一个字节数据与配置的Address匹配后接收总线空闲时触发。在中断函数使用 uart_is_addr_match_and_rxidle API判断是否触发。

      • 中断标志清零:使用 uart_clear_addr_match_and_rxidle_flag API 清零。

      • 注意 具体支持参考每个SOC的 hpm_soc_ip_feature.hHPM_IP_FEATURE_UART_ADDR_MATCH 宏定义

    • uart_intr_addr_datalost

      • 中断触发条件:在地址匹配前的数据会抛弃,然后产生中断,在中断函数使用 uart_is_data_lost API判断是否触发。比如准备两组数据,数据组1(没带可匹配的地址)在数据组2(带匹配的地址)之前产生中断,数据组1数据会抛弃。

      • 中断标志清零:使用 uart_clear_data_lost_flag API 清零。

      • 注意 具体支持参考每个SOC的 hpm_soc_ip_feature.hHPM_IP_FEATURE_UART_ADDR_MATCH 宏定义

    • uart_intr_errf

      • 中断触发条件:接收 fifo 错误标志位,在 fifo 模式下,出现奇偶校验错误、帧错误或传输打断错误时触发,在中断函数使用 uart_rx_is_fifo_error API判断是否触发。

      • 中断标志清零:使用 uart_clear_rx_fifo_error_flag API 清零。

      • 注意 具体支持参考每个SOC的 hpm_soc_ip_feature.hHPM_IP_FEATURE_UART_RX_LINE_ERROR_DETECT 宏定义

    • uart_intr_framing_err

      • 中断触发条件:在出现帧格式错误时触发,在中断函数使用 uart_rx_is_framing_error API判断是否触发。

      • 中断标志清零:使用 uart_clear_rx_framing_error_flag API 清零。

      • 注意 具体支持在SOC的 hpm_soc_ip_feature.hHPM_IP_FEATURE_UART_RX_LINE_ERROR_DETECT 宏定义

    • uart_intr_break_err

      • 中断触发条件:在出现传输打断错误时产生时触发,在中断函数使用 uart_rx_is_break API判断是否触发。

      • 中断标志清零:使用 uart_clear_rx_break_flag API 清零。

      • 注意 具体支持参考每个SOC的 hpm_soc_ip_feature.hHPM_IP_FEATURE_UART_RX_LINE_ERROR_DETECT 宏定义

    • uart_intr_parity_err

      • 中断触发条件:在出现奇偶校验错误时触发,在中断函数使用 uart_rx_is_parity_error API判断是否触发。

      • 中断标志清零:使用 uart_clear_rx_parity_error_flag API 清零。

      • 注意 具体支持参考每个SOC的 hpm_soc_ip_feature.hHPM_IP_FEATURE_UART_RX_LINE_ERROR_DETECT 宏定义

    • uart_intr_overrun

      • 中断触发条件:接收数据过载时触发,在中断函数使用 uart_rx_is_overrun API判断是否触发。

      • 中断标志清零:使用 uart_clear_rx_overrun_flag API 清零。

      • 注意

        • 具体支持参考每个SOC的 hpm_soc_ip_feature.hHPM_IP_FEATURE_UART_RX_LINE_ERROR_DETECT 宏定义

        • 在具有32字节FIFO的SOC下,由于存在1字节异步FIFO,接收到33字节数据时,才会触发。

  • 相关API接口:

    • 使能UART中断

      void uart_enable_irq(UART_Type *ptr, uint32_t irq_mask);
      
      • 参数说明:

        参数名

        类型

        描述

        ptr

        UART_Type*

        指向UART控制器基地址的指针,用于指定要配置的UART控制器。

        irq_mask

        uint32_t

        中断掩码,用于指定要使能的中断。对应的中断掩码可以从 uart_intr_enable_t 枚举类型中查看。

      • 返回值:

    • 禁用UART中断

      void uart_disable_irq(UART_Type *ptr, uint32_t irq_mask)
      
      • 参数说明:

        参数名

        类型

        描述

        ptr

        UART_Type*

        指向UART控制器基地址的指针,用于指定要配置的UART控制器。

        irq_mask

        uint32_t

        中断掩码,用于指定要使能的中断。对应的中断掩码可以从 uart_intr_enable_t 枚举类型中查看。

      • 返回值:

67.6. uart示例