text: /**
   * @file uart.c
   * @author JL
   * @brief 串口UART模块C文件
   * @version 1.2
   * @date 2018-11-22
   */
  
  #include "asm/clock.h"
  #include "asm/uart_dev.h"
  #include "asm/cpu.h"
  #include "generic/gpio.h"
  #include "spinlock.h"
  
  #ifdef SUPPORT_MS_EXTENSIONS
  #pragma bss_seg(".uart_bss")
  #pragma data_seg(".uart_data")
  #pragma const_seg(".uart_const")
  #pragma code_seg(".uart_code")
  #endif
  
  #define UART_CLK  clk_get("uart")
  
  
  
  static uart_bus_t uart0;
  static uart_bus_t uart1;
  static uart_bus_t uart2;
  
  /* _WEAK_ */
  /* extern */
  const u32 CONFIG_UART0_ENABLE = 1;
  
  /* _WEAK_ */
  /* extern */
  const u32 CONFIG_UART1_ENABLE  = 1;
  
  /* _WEAK_ */
  /* extern */
  const u32 CONFIG_UART2_ENABLE  = 1;
  
  /* _WEAK_ */
  /* extern */
  const u32 CONFIG_UART0_ENABLE_TX_DMA =  1;
  
  /* _WEAK_ */
  /* extern */
  const u32 CONFIG_UART1_ENABLE_TX_DMA =  1;
  
  /* _WEAK_ */
  /* extern */
  const u32 CONFIG_UART2_ENABLE_TX_DMA =  1;
  
  static u32 kfifo_get(KFIFO *kfifo, u8 *buffer, u32 len)
  {
      unsigned int i;
      len = MIN(len, kfifo->buf_in - kfifo->buf_out);
  
      i = MIN(len, kfifo->buf_size - (kfifo->buf_out & (kfifo->buf_size - 1)));
  
      memcpy(buffer, kfifo->buffer + (kfifo->buf_out & (kfifo->buf_size - 1)), i);
  
      memcpy(buffer + i, kfifo->buffer, len - i);
  
      kfifo->buf_out += len;
      return len;
  
  }
  static u32 kfifo_length(KFIFO *kfifo)
  {
      return kfifo->buf_in - kfifo->buf_out;
  }
  /**
   * @brief ut0发送一个byte
   *
   * @param a 要发送的字节
   */
  static void UT0_putbyte(char a)
  {
      if (JL_UART0->CON0 & BIT(0)) {
          JL_UART0->BUF = a;
          __asm__ volatile("csync");
          while ((JL_UART0->CON0 & BIT(15)) == 0);
          JL_UART0->CON0 |= BIT(13);
      }
  }
  /**
   * @brief ut0接收一个byte
   *
   * @param buf 字节存放地址
   * @param timeout 接收超时时间，单位1ms
   * @return 返回0：接收失败；返回1：接收成功
   */
  static u8 UT0_getbyte(u8 *buf, u32 timeout)
  {
      u32 _timeout, _t_sleep;
      timeout = ut_msecs_to_jiffies(timeout);
      if (JL_UART0->CON0 & BIT(6)) {
          //DMA_MODE
          if (!kfifo_length(&uart0.kfifo)) {
              UT_OSSemPend(&uart0.sem_rx, timeout);
          }
          UT_OSSemSet(&uart0.sem_rx, 0);
  
          return kfifo_get(&uart0.kfifo, buf, 1);
      } else {
          _timeout = timeout + ut_get_jiffies();
          _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies();
          while (!(JL_UART0->CON0 & BIT(14))) {
              if (timeout && time_before(_timeout, ut_get_jiffies())) {
                  return 0;
              }
              if (time_before(_t_sleep, ut_get_jiffies())) {
                  ut_sleep();
                  _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies();
              }
          }
          *buf = JL_UART0->BUF;
          JL_UART0->CON0 |= BIT(12);
          __asm__ volatile("csync");  //make RX_PND_CLR taking effect
      }
      return 1;
  }
  /**
   * @brief ut0中断函数
   */
  SET_INTERRUPT
  static void UT0_isr_fun(void)
  {
      u32 rx_len = 0;
      if ((JL_UART0->CON0 & BIT(2)) && (JL_UART0->CON0 & BIT(15))) {
          JL_UART0->CON0 |= BIT(13);
          UT_OSSemPost(&uart0.sem_tx);
          if (uart0.isr_cbfun) {
              uart0.isr_cbfun(&uart0, UT_TX);
          }
      }
      if ((JL_UART0->CON0 & BIT(3)) && (JL_UART0->CON0 & BIT(14))) {
          JL_UART0->CON0 |= BIT(12);           //清RX PND
          uart0.kfifo.buf_in += uart0.frame_length; //每满frame_length字节则产生一次中断
          UT_OSSemPost(&uart0.sem_rx);
          if (uart0.isr_cbfun) {
              uart0.isr_cbfun(&uart0, UT_RX);
          }
      }
      if ((JL_UART0->CON0 & BIT(5)) && (JL_UART0->CON0 & BIT(11))) {
          //OTCNT PND
          JL_UART0->CON0 |= BIT(7);                     //DMA模式
          JL_UART0->CON0 |= BIT(10);                    //清OTCNT PND
          JL_UART0->CON0 |= BIT(12);                    //清RX PND(这里的顺序不能改变，这里要清一次)
          rx_len = JL_UART0->HRXCNT;             //读当前串口接收数据的个数
  
          if (rx_len) {
              uart0.kfifo.buf_in += rx_len;
              /* printf("%s() %d\n", __func__, __LINE__); */
              UT_OSSemPost(&uart0.sem_rx);
              if (uart0.isr_cbfun) {
                  uart0.isr_cbfun(&uart0, UT_RX_OT);
              }
          }
      }
  }
  /**
   * @brief ut0接收字符串
   *
   * @param buf 字符串存放首地址
   * @param len 预接收长度
   * @param timeout 接收超时时间，单位1ms
   * @return 返回实际接收长度
   */
  static u32 UT0_read_buf(u8 *buf, u32 len, u32 timeout)
  {
      u32 i;
      u32 _timeout, _t_sleep;
      if (len == 0) {
          return 0;
      }
      timeout = ut_msecs_to_jiffies(timeout);
      if (JL_UART0->CON0 & BIT(6)) {
  
          if (!kfifo_length(&uart0.kfifo)) {
              UT_OSSemPend(&uart0.sem_rx, timeout);
          }
          UT_OSSemSet(&uart0.sem_rx, 0);
  
          return kfifo_get(&uart0.kfifo, buf, len);
      } else {
          _timeout = timeout + ut_get_jiffies();
          _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies();
          for (i = 0; i < len; i++) {
              while (!(JL_UART0->CON0 & BIT(14))) {
                  if (timeout && time_before(_timeout, ut_get_jiffies())) {
                      return i;
                  }
                  if (time_before(_t_sleep, ut_get_jiffies())) {
                      ut_sleep();
                      _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies();
                  }
              }
              *(buf + i) = JL_UART0->BUF;
              JL_UART0->CON0 |= BIT(12);
              __asm__ volatile("csync");  //make RX_PND_CLR taking effect
          }
      }
      return len;
  }
  /**
   * @brief ut0发送字符串
   *
   * @param buf 字符串首地址
   * @param len 发送的字符串长度
   */
  static void UT0_write_buf(const u8 *buf, u32 len)
  {
      u32 i;
      if (len == 0) {
          return;
      }
      if (CONFIG_UART0_ENABLE_TX_DMA) {
          UT_OSSemSet(&uart0.sem_tx, 0);
          JL_UART0->CON0 |= BIT(13);
          JL_UART0->CON0 |= BIT(2);
          JL_UART0->TXADR = (u32)buf;
          JL_UART0->TXCNT = len;
          UT_OSSemPend(&uart0.sem_tx, 0);
          JL_UART0->CON0 &= ~BIT(2);
      } else {
          for (i = 0; i < len; i ++) {
              UT0_putbyte(*(buf + i));
          }
      }
  }
  /**
   * @brief ut0配置波特率
   *
   * @param baud 波特率值
   */
  static void UT0_set_baud(u32 baud)
  {
      JL_UART0->CON0 &= ~(BIT(0) | BIT(1));
      JL_UART0->CON0 |= BIT(13) | BIT(12) | BIT(10);
      JL_UART0->BAUD = ((UART_CLK + baud / 2) / baud) / 4 - 1;
      if (JL_UART0->CON0 & BIT(5)) {
          if (uart0.rx_timeout > 10) {
              JL_UART0->OTCNT = (uart0.rx_timeout / 10) * (UART_CLK / 10) / 10;
          } else {
              JL_UART0->OTCNT = uart0.rx_timeout * UART_CLK / 1000;
          }
      }
      JL_UART0->CON0 |= BIT(13) | BIT(12) | BIT(10) | BIT(0) | BIT(1);
  }
  /**
   * @brief ut0使能
   */
  static void UT0_open(u32 baud, u32 is_9bit, void *cbuf, u32 cbuf_size, u32 rx_cnt, u32 ot)
  {
      JL_UART0->CON0 = BIT(13) | BIT(12) | BIT(10);
      UT_OSSemCreate(&uart0.sem_rx, 0);
      UT_OSSemCreate(&uart0.sem_tx, 0);
      request_irq(IRQ_UART0_IDX, 3, UT0_isr_fun, 0);
      if (cbuf) {
          uart0.kfifo.buffer = cbuf;
          uart0.kfifo.buf_size = cbuf_size;
          uart0.kfifo.buf_in = 0;
          uart0.kfifo.buf_out = 0;
          uart0.frame_length = rx_cnt;
          uart0.rx_timeout = ot;
          JL_UART0->RXSADR = (u32)uart0.kfifo.buffer;
          JL_UART0->RXEADR = (u32)(uart0.kfifo.buffer + uart0.kfifo.buf_size);
          JL_UART0->RXCNT = uart0.frame_length;
          JL_UART0->CON0 |= BIT(6) | BIT(5) | BIT(3);
      }
      if (is_9bit) {
          JL_UART0->CON2 |= BIT(0);
      } else {
          JL_UART0->CON2 &= ~BIT(0);
      }
      UT0_set_baud(baud);
  }
  /**
   * @brief ut0关闭，注销
   */
  static void UT0_close(void)
  {
      UT_OSSemClose(&uart0.sem_rx);
      UT_OSSemClose(&uart0.sem_tx);
      irq_disable(IRQ_UART0_IDX);
      JL_UART0->CON0 = BIT(13) | BIT(12) | BIT(10);
  }
  /**
   * @brief ut1发送一个byte
   *
   * @param a 要发送的字节
   */
  static void UT1_putbyte(char a)
  {
      if (JL_UART1->CON0 & BIT(0)) {
          JL_UART1->BUF = a;
          __asm__ volatile("csync");
          while ((JL_UART1->CON0 & BIT(15)) == 0);
          JL_UART1->CON0 |= BIT(13);
      }
  }
  /**
   * @brief ut1接收一个byte
   *
   * @param buf 字节存放地址
   * @param timeout 接收超时时间，单位1ms
  10ms¥；返回1：接收成功
   */
  static u8 UT1_getbyte(u8 *buf, u32 timeout)
  {
      u32 _timeout, _t_sleep;
      timeout = ut_msecs_to_jiffies(timeout);
      if (JL_UART1->CON0 & BIT(6)) {
          if (!kfifo_length(&uart1.kfifo)) {
              UT_OSSemPend(&uart1.sem_rx, timeout);
          }
          UT_OSSemSet(&uart1.sem_rx, 0);
  
          return kfifo_get(&uart1.kfifo, buf, 1);
      } else {
          _timeout = timeout + ut_get_jiffies();
          _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies();
          while (!(JL_UART1->CON0 & BIT(14))) {
              if (timeout && time_before(_timeout, ut_get_jiffies())) {
                  return 0;
              }
              if (time_before(_t_sleep, ut_get_jiffies())) {
                  ut_sleep();
                  _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies();
              }
          }
          *buf = JL_UART1->BUF;
          JL_UART1->CON0 |= BIT(12);
          __asm__ volatile("csync");  //make RX_PND_CLR taking effect
      }
      return 1;
  }
  /**
   * @brief ut1中断函数
   */
  SET_INTERRUPT
  static void UT1_isr_fun(void)
  {
      u32 rx_len = 0;
      if ((JL_UART1->CON0 & BIT(2)) && (JL_UART1->CON0 & BIT(15))) {
          JL_UART1->CON0 |= BIT(13);
          UT_OSSemPost(&uart1.sem_tx);
          if (uart1.isr_cbfun) {
              uart1.isr_cbfun(&uart1, UT_TX);
          }
      }
      if ((JL_UART1->CON0 & BIT(3)) && (JL_UART1->CON0 & BIT(14))) {
          JL_UART1->CON0 |= BIT(12);           //清RX PND
          uart1.kfifo.buf_in += uart1.frame_length; //每满32字节则产生一次中断
          UT_OSSemPost(&uart1.sem_rx);
          if (uart1.isr_cbfun) {
              uart1.isr_cbfun(&uart1, UT_RX);
          }
      }
  
      if ((JL_UART1->CON0 & BIT(5)) && (JL_UART1->CON0 & BIT(11))) {
          //OTCNT PND
          JL_UART1->CON0 |= BIT(7);                     //DMA模式
          JL_UART1->CON0 |= BIT(10);                    //清OTCNT PND
          JL_UART1->CON0 |= BIT(12);                    //清RX PND(这里的顺序不能改变，这里要清一次)
          rx_len = JL_UART1->HRXCNT;             //读当前串口接收数据的个数
  
          if (rx_len) {
              uart1.kfifo.buf_in += rx_len;
              /* printf("%s() %d\n", __func__, __LINE__); */
              UT_OSSemPost(&uart1.sem_rx);
              if (uart1.isr_cbfun) {
                  uart1.isr_cbfun(&uart1, UT_RX_OT);
              }
          }
      }
  }
  /**
   * @brief ut1接收字符串
   *
   * @param buf 字符串存放首地址
   * @param len 预接收长度
   * @param timeout 接收超时时间，单位1ms
   * @return 返回实际接收的长度
   */
  static u32 UT1_read_buf(u8 *buf, u32 len, u32 timeout)
  {
      u32 i;
      u32 _timeout, _t_sleep;
      if (len == 0) {
          return 0;
      }
      timeout = ut_msecs_to_jiffies(timeout);
      if (JL_UART1->CON0 & BIT(6)) {
          if (!kfifo_length(&uart1.kfifo)) {
              UT_OSSemPend(&uart1.sem_rx, timeout);
          }
          UT_OSSemSet(&uart1.sem_rx, 0);
  
          return kfifo_get(&uart1.kfifo, buf, len);
      } else {
          _timeout = timeout + ut_get_jiffies();
          _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies();
          for (i = 0; i < len; i++) {
              while (!(JL_UART1->CON0 & BIT(14))) {
                  if (timeout && time_before(_timeout, ut_get_jiffies())) {
                      return i;
                  }
                  if (time_before(_t_sleep, ut_get_jiffies())) {
                      ut_sleep();
                      _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies();
                  }
              }
              *(buf + i) = JL_UART1->BUF;
              JL_UART1->CON0 |= BIT(12);
              __asm__ volatile("csync");  //make RX_PND_CLR taking effect
          }
      }
      return len;
  }
  /**
   * @brief ut1发送字符串
   *
   * @param buf 字符串首地址
   * @param len 发送的字符串长度
   * @param timeout 发送超时时间，单位10ms
   */
  static void UT1_write_buf(const u8 *buf, u32 len)
  {
      u32 i;
      if (len == 0) {
          return;
      }
      if (CONFIG_UART1_ENABLE_TX_DMA) {
          UT_OSSemSet(&uart1.sem_tx, 0);
          JL_UART1->CON0 |= BIT(13);
          JL_UART1->CON0 |= BIT(2);
          JL_UART1->TXADR = (u32)buf;
          JL_UART1->TXCNT = len;
          UT_OSSemPend(&uart1.sem_tx, 0);
          JL_UART1->CON0 &= ~BIT(2);
      } else {
          for (i = 0; i < len; i ++) {
              UT1_putbyte(*(buf + i));
          }
      }
  }
  /**
   * @brief ut1配置波特率
   *
   * @param baud 波特率值
   */
  static void UT1_set_baud(u32 baud)
  {
      JL_UART1->CON0 &= ~(BIT(0) | BIT(1));
      JL_UART1->CON0 |= BIT(13) | BIT(12) | BIT(10);
      JL_UART1->BAUD = ((UART_CLK + baud / 2) / baud) / 4 - 1;
      if (JL_UART1->CON0 & BIT(5)) {
          if (uart1.rx_timeout > 10) {
              JL_UART1->OTCNT = (uart1.rx_timeout / 10) * (UART_CLK / 10) / 10;
          } else {
              JL_UART1->OTCNT = uart1.rx_timeout * UART_CLK / 1000;
          }
      }
      JL_UART1->CON0 |= BIT(13) | BIT(12) | BIT(10) | BIT(0) | BIT(1);
  }
  /**
   * @brief ut1使能
   */
  static void UT1_open(u32 baud, u32 is_9bit, void *cbuf, u32 cbuf_size, u32 rx_cnt, u32 ot)
  {
      JL_UART1->CON0 = BIT(13) | BIT(12) | BIT(10);
      UT_OSSemCreate(&uart1.sem_rx, 0);
      UT_OSSemCreate(&uart1.sem_tx, 0);
      request_irq(IRQ_UART1_IDX, 3, UT1_isr_fun, 0);
      if (cbuf) {
          uart1.kfifo.buffer = cbuf;
          uart1.kfifo.buf_size = cbuf_size;
          uart1.kfifo.buf_in = 0;
          uart1.kfifo.buf_out = 0;
          uart1.frame_length = rx_cnt;
          uart1.rx_timeout = ot;
          JL_UART1->RXSADR = (u32)uart1.kfifo.buffer;
          JL_UART1->RXEADR = (u32)(uart1.kfifo.buffer + uart1.kfifo.buf_size);
          JL_UART1->RXCNT = uart1.frame_length;
          JL_UART1->CON0 |= BIT(6) | BIT(5) | BIT(3);
      }
      if (is_9bit) {
          JL_UART1->CON2 |= BIT(0);
      } else {
          JL_UART1->CON2 &= ~BIT(0);
      }
      UT1_set_baud(baud);
  }
  /**
   * @brief ut1关闭，注销
   */
  static void UT1_close(void)
  {
      UT_OSSemClose(&uart1.sem_rx);
      UT_OSSemClose(&uart1.sem_tx);
      irq_disable(IRQ_UART1_IDX);
      JL_UART1->CON0 = BIT(13) | BIT(12) | BIT(10);
  }
  /**
   * @brief ut2发送一个byte
   *
   * @param a 要发送的字节
   */
  static void UT2_putbyte(char a)
  {
      if (JL_UART2->CON0 & BIT(0)) {
          JL_UART2->BUF = a;
          __asm__ volatile("csync");
          while ((JL_UART2->CON0 & BIT(15)) == 0);
          JL_UART2->CON0 |= BIT(13);
      }
  }
  /**
   * @brief ut2接收一个byte
   *
   * @param buf 字节存放地址
   * @param timeout 接收超时时间，单位1ms
   * @return 返回0：接收失败；返回1：接收成功
   */
  static u8 UT2_getbyte(u8 *buf, u32 timeout)
  {
      u32 _timeout, _t_sleep;
      timeout = ut_msecs_to_jiffies(timeout);
  
      if (JL_UART2->CON0 & BIT(6)) {
          if (!kfifo_length(&uart2.kfifo)) {
              UT_OSSemPend(&uart2.sem_rx, timeout);
          }
          UT_OSSemSet(&uart2.sem_rx, 0);
      } else {
          _timeout = timeout + ut_get_jiffies();
          _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies();
          while (!(JL_UART2->CON0 & BIT(14))) {
              if (timeout && time_before(_timeout, ut_get_jiffies())) {
                  return 0;
              }
              if (time_before(_t_sleep, ut_get_jiffies())) {
                  ut_sleep();
                  _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies();
              }
          }
          *buf = JL_UART2->BUF;
          JL_UART2->CON0 |= BIT(12);
          __asm__ volatile("csync");  //make RX_PND_CLR taking effect
      }
  
      return 1;
  }
  /**
   * @brief ut2中断函数
   */
  SET_INTERRUPT
  static void UT2_isr_fun(void)
  {
      //JL_UART2->CON0 |= (BIT(13) | BIT(12) | BIT(10));
      u32 rx_len = 0;
      if ((JL_UART2->CON0 & BIT(2)) && (JL_UART2->CON0 & BIT(15))) {
          JL_UART2->CON0 |= BIT(13);
          UT_OSSemPost(&uart2.sem_tx);
          if (uart2.isr_cbfun) {
              uart2.isr_cbfun(&uart2, UT_TX);
          }
      }
      if ((JL_UART2->CON0 & BIT(3)) && (JL_UART2->CON0 & BIT(14))) {
          JL_UART2->CON0 |= BIT(12);           //清RX PND
          uart2.kfifo.buf_in += uart2.frame_length; //每满32字节则产生一次中断
          UT_OSSemPost(&uart2.sem_rx);
          if (uart2.isr_cbfun) {
              uart2.isr_cbfun(&uart2, UT_RX);
          }
      }
  
      if ((JL_UART2->CON0 & BIT(5)) && (JL_UART2->CON0 & BIT(11))) {
          //OTCNT PND
          JL_UART2->CON0 |= BIT(7);                     //DMA模式
          JL_UART2->CON0 |= BIT(10);                    //清OTCNT PND
          JL_UART2->CON0 |= BIT(12);                    //清RX PND(这里的顺序不能改变，这里要清一次)
          rx_len = JL_UART2->HRXCNT;             //读当前串口接收数据的个数
  
          if (rx_len) {
              uart2.kfifo.buf_in += rx_len;
              /* printf("%s() %d\n", __func__, __LINE__); */
              UT_OSSemPost(&uart2.sem_rx);
              if (uart2.isr_cbfun) {
                  uart2.isr_cbfun(&uart2, UT_RX_OT);
              }
          }
      }
  }
  
  /**
   * @brief ut1接收字符串
   *
   * @param buf 字符串存放首地址
   * @param len 预接收长度
   * @param timeout 接收超时时间，单位1ms
   * @return 返回实际接收的长度
   */
  static u32 UT2_read_buf(u8 *buf, u32 len, u32 timeout)
  {
      u32 i;
      u32 _timeout, _t_sleep;
      if (len == 0) {
          return 0;
      }
  
      timeout = ut_msecs_to_jiffies(timeout);
      if (JL_UART2->CON0 & BIT(6)) {
          if (!kfifo_length(&uart2.kfifo)) {
              UT_OSSemPend(&uart2.sem_rx, timeout);
          }
          UT_OSSemSet(&uart2.sem_rx, 0);
          return kfifo_get(&uart2.kfifo, buf, len);
      } else {
          _timeout = timeout + ut_get_jiffies();
          _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies();
          for (i = 0; i < len; i ++) {
              while (!(JL_UART2->CON0 & BIT(14))) {
                  if (timeout && time_before(_timeout, ut_get_jiffies())) {
                      return i;
                  }
                  if (time_before(_t_sleep, ut_get_jiffies())) {
                      ut_sleep();
                      _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies();
                  }
              }
              *(buf + i) = JL_UART2->BUF;
              JL_UART2->CON0 |= BIT(12);
              __asm__ volatile("csync");  //make RX_PND_CLR taking effect
          }
      }
      return len;
  }
  /**
   * @brief ut2发送字符串
   *
   * @param buf 字符串首地址
   * @param len 发送的字符串长度
   * @param timeout 发送超时时间，单位10ms
   */
  static void UT2_write_buf(const u8 *buf, u32 len)
  {
      u32 i;
      if (len == 0) {
          return;
      }
      for (i = 0; i < len; i ++) {
          UT2_putbyte(*(buf + i));
      }
      if (CONFIG_UART2_ENABLE_TX_DMA) {
          UT_OSSemSet(&uart2.sem_tx, 0);
          JL_UART2->CON0 |= BIT(13);
          JL_UART2->CON0 |= BIT(2);
          JL_UART2->TXADR |= (u32)buf;
          JL_UART2->TXCNT |= len;
          UT_OSSemPend(&uart2.sem_tx, 0);
          JL_UART2->CON0 &= ~BIT(2);
      } else {
          for (i = 0; i < len; i++) {
              UT2_putbyte(*(buf + i));
          }
      }
  }
  /**
   * @brief ut2配置波特率
   *
   * @param baud 波特率值
   */
  static void UT2_set_baud(u32 baud)
  {
      JL_UART2->CON0 &= ~(BIT(0) | BIT(1));
      JL_UART2->CON0 |= BIT(13) | BIT(12) | BIT(10);
      JL_UART2->BAUD = ((UART_CLK + baud / 2) / baud) / 4 - 1;
      if (JL_UART2->CON2 & BIT(5)) {
          if (uart2.rx_timeout > 10) {
              JL_UART2->OTCNT = (uart1.rx_timeout / 10) * (UART_CLK / 10) / 10;
          } else {
              JL_UART2->OTCNT = uart1.rx_timeout * UART_CLK / 1000;
          }
      }
      JL_UART2->CON0 |= BIT(13) | BIT(12) | BIT(10) | BIT(0) | BIT(1);
  }
  
  /**
   * @brief ut2使能
   */
  static void UT2_open(u32 baud, u32 is_9bit, void *cbuf, u32 cbuf_size, u32 rx_cnt, u32 ot)
  {
      JL_UART2->CON0 = BIT(13) | BIT(12) | BIT(10);
      UT_OSSemCreate(&uart2.sem_rx, 0);
      UT_OSSemCreate(&uart2.sem_tx, 0);
      request_irq(IRQ_UART2_IDX, 3, UT2_isr_fun, 0);
      if (cbuf) {
          uart2.kfifo.buffer = cbuf;
          uart2.kfifo.buf_size = cbuf_size;
          uart2.kfifo.buf_in = 0;
          uart2.kfifo.buf_out = 0;
          uart2.frame_length = rx_cnt;
          uart2.rx_timeout = ot;
          JL_UART2->RXSADR = (u32)uart2.kfifo.buffer;
          JL_UART2->RXEADR = (u32)(uart2.kfifo.buffer + uart2.kfifo.buf_size);
          JL_UART2->RXCNT = uart2.frame_length;
          JL_UART2->CON0 |= BIT(6) | BIT(5) | BIT(3);
      }
      if (is_9bit) {
          JL_UART2->CON2 |= BIT(0);
      } else {
          JL_UART2->CON2 &= ~BIT(0);
      }
      UT2_set_baud(baud);
  }
  
  /**
   * @brief ut2关闭，注销
   */
  static void UT2_close(void)
  {
      UT_OSSemClose(&uart2.sem_rx);
      UT_OSSemClose(&uart2.sem_tx);
      JL_UART2->CON0 &= ~(BIT(5) | BIT(3) | BIT(2) | BIT(0));
      JL_UART2->CON0 = BIT(13) | BIT(12) | BIT(10);
  }
  
  static u32 uart_is_idle(u32 ut_num)
  {
      switch (ut_num) {
      case 0 :
          return !(JL_UART0->CON0 & BIT(0));
      case 1 :
          return !(JL_UART1->CON0 & BIT(0));
      case 2:
          return !(JL_UART2->CON0 & BIT(0));
      default :
          break;
      }
      return 0;
  }
  
  static u8 uart_config(const struct uart_platform_data_t *arg, u8 tx_ch, enum PFI_TABLE rx_pfun)
  {
      if (!(arg->tx_pin < IO_PORT_MAX || arg->rx_pin < IO_PORT_MAX)) {
          return -1;
      }
  
      if (arg->tx_pin) {
          gpio_direction_output(arg->tx_pin, 1);
          gpio_set_fun_output_port(arg->tx_pin, tx_ch, 1, 1);
      }
      if (arg->rx_pin) {
          gpio_direction_input(arg->rx_pin);
          gpio_set_pull_up(arg->rx_pin, 1);
          gpio_set_die(arg->rx_pin, 1);
          gpio_set_fun_input_port(arg->rx_pin, rx_pfun);
      }
      return 0;
  }
  
  #if FLOW_CONTROL
  void flow_ctl_hw_init(void)
  {
      struct uart_platform_data_t arg;
      arg.tx_pin = IO_PORTA_06;
      arg.rx_pin = IO_PORTA_05;
      uart_config(&arg, FO_UART1_RTS, PFI_UART1_CTS);
      JL_UART1->CON1 = BIT(14) | BIT(13) | BIT(3) | BIT(2) | BIT(1) | BIT(0);
  }
  #endif
  
  /**
   * @brief ut模块初始const struct uart_platform_data_t *arg化函数，供外部调用
   *
   * @param arg 传入uartconst struct uart_platform_data_t *arg_argment型结构体指针
   * @return 返回uart_buconst struct uart_platform_data_t *args_t型结构体指针
   */
  __attribute__((noinline))
  const uart_bus_t *uart_dev_open(const struct uart_platform_data_t *arg)
  {
      u8 ut_num;
      uart_bus_t *ut = NULL;
      u8 gpio_input_channle_flag = 0;
  
      if (uart_is_idle(0)) {
          ut_num = 0;
      } else if (uart_is_idle(1)) {
          ut_num = 1;
      } else if ((uart_is_idle(2)) && (!arg->rx_cbuf)) {
          ut_num = 2;
      } else {
          return NULL;
      }
      if (arg->rx_cbuf) {
          if ((arg->rx_cbuf_size == 0) || (arg->rx_cbuf_size & (arg->rx_cbuf_size - 1))) {
              return NULL;
          }
      }
  
      if (CONFIG_UART0_ENABLE && ut_num == 0) {
          //gpio_set_uart0(ut_ch);
          if (uart_config(arg, FO_UART0_TX, PFI_UART0_RX)) {
              return NULL;
          }
  
          uart0.argv = arg->argv;
          uart0.isr_cbfun = arg->isr_cbfun;
          uart0.putbyte = UT0_putbyte;
          uart0.getbyte = UT0_getbyte;
          uart0.read = UT0_read_buf;
          uart0.write = UT0_write_buf;
          uart0.set_baud = UT0_set_baud;
          UT0_open(arg->baud, arg->is_9bit,
                   arg->rx_cbuf, arg->rx_cbuf_size,
                   arg->frame_length, arg->rx_timeout);
          ut = &uart0;
      } else if (CONFIG_UART1_ENABLE && ut_num == 1) {
          //gpio_set_uart1(ut_ch);
          if (uart_config(arg, FO_UART1_TX, PFI_UART1_RX)) {
              return NULL;
          }
          uart1.argv = arg->argv;
          uart1.isr_cbfun = arg->isr_cbfun;
          uart1.putbyte = UT1_putbyte;
          uart1.getbyte = UT1_getbyte;
          uart1.read    = UT1_read_buf;
          uart1.write   = UT1_write_buf;
          uart1.set_baud = UT1_set_baud;
          UT1_open(arg->baud, arg->is_9bit,
                   arg->rx_cbuf, arg->rx_cbuf_size,
                   arg->frame_length, arg->rx_timeout);
          ut = &uart1;
      } else if (CONFIG_UART2_ENABLE && ut_num == 2) {
          //gpio_set_uart2(ut_ch);
          if (uart_config(arg, FO_UART2_TX, PFI_UART2_RX)) {
              return NULL;
          }
          uart2.argv = arg->argv;
          uart2.isr_cbfun = arg->isr_cbfun;
          uart2.putbyte = UT2_putbyte;
          uart2.getbyte = UT2_getbyte;
          uart2.read    = UT2_read_buf;
          uart2.write   = UT2_write_buf;
          uart2.set_baud = UT2_set_baud;
          UT2_open(arg->baud, arg->is_9bit,
                   arg->rx_cbuf, arg->rx_cbuf_size,
                   arg->frame_length, arg->rx_timeout);
          ut = &uart2;
      } else {
          return NULL;
      }
      return ut;
  }
  u32 uart_dev_close(uart_bus_t *ut)
  {
      UT_OSSemClose(&ut->sem_rx);
      UT_OSSemClose(&ut->sem_tx);
      if (&uart0 == ut) {
          UT0_close();
          return gpio_close_uart0();
      } else if (&uart1 == ut) {
          UT1_close();
          return gpio_close_uart1();
      } else {
          UT2_close();
          return gpio_close_uart2();
      }
      return 0;
  }
  void uart_disable_for_ota()
  {
      JL_UART0->CON0 = BIT(13) | BIT(12) | BIT(10);
      JL_UART1->CON0 = BIT(13) | BIT(12) | BIT(10);
      JL_UART2->CON0 = BIT(13) | BIT(12) | BIT(10);
  }
  
  
  
  
  
  
  