lpuart0_drv.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #include "board.h"
  2. void lpuart0_drv_init(uint8_t baud)
  3. {
  4. // LPUART0_RX: PD09(AF1)
  5. GpioInit(PD09_LPUART0_RXD, GPIO_DIG_IN_PULLUP_NONEDOWN);
  6. PeriClk_MutEnable(PeriClk_LpUart0);
  7. M0P_LPUART0->SCON = (0<<21) | // FEIE, Frame error interrupt 0:close; 1:open;
  8. (0<<17) | // DMATXEN, TX DMAC handshake 0:close; 1:open;
  9. (0<<16) | // DMARXEN, RX DMAC handshake 0:close; 1:open;
  10. (0<<14) | // STOPBIT, Stop bit length, 0:1-bit; 1:1.5-bits; 2:2-bits; 3:RSV
  11. (0<<13) | // PEIE, Parity error interrupt 0:close; 1:open;
  12. (baud<<11) | // SCLKSEL, 0,1:PCLK; 2:XTL; 3:RCL;
  13. (2<<9) | // OVER, 0:16x-sample; 1:8x-sample; 2:4x-sample;
  14. (0<<8) | // TXEIE, TX empty interrupt 0:close; 1:open;
  15. (1<<6) | // SM, 0:mode0; 1:mode1; 2:mode2; 3:mode3;
  16. (1<<4) | // REN, in mode1 0:TX only; 1:RX/TX
  17. (0<<1) | // TCIE, Tx completed interrupt 0:close; 1:open;
  18. (1<<0); // RCIE, Rx completed interrupt 0:close; 1:open;
  19. // BaudRate = fSCLK/(OVER*SCNT) = 16MHz/(4*35) = 114286 baud (-0.79%).
  20. if (baud == 3)
  21. {
  22. M0P_LPUART0->SCNT = 1; // 9600
  23. }
  24. else
  25. {
  26. M0P_LPUART0->SCNT = 35; // 115200
  27. }
  28. // enable interrupt at NVIC side
  29. IRQMutEnable(LPUART0_IRQn, NVIC_PRIO_3);
  30. // IRQMutEnable(LPUART1_IRQn, NVIC_PRIO_0);
  31. // LPUART0_TX: PD08(AF1)
  32. GpioInit(PD08_LPUART0_TXD,
  33. GPIO_DIG_OUT_STRN_PUSH_NONEUP_NONEDOWN);
  34. SerPlot.f.Preamble = 0xFFFFFFFF;
  35. }
  36. static uart_rx_itf Lpuart0RxItf;
  37. void lpuart0_set_rx_itf(uart_rx_itf itf) {
  38. Lpuart0RxItf = itf;
  39. }
  40. // interrupt routine
  41. void LPUART0_IRQHandler(void)
  42. {
  43. union {
  44. uint32_t ISR;
  45. stc_uart_isr_field_t ISR_f;
  46. } IRQ;
  47. #ifdef FINSH_TXBUF_DEPTH
  48. rt_base_t level;
  49. #endif
  50. IRQ.ISR = M0P_LPUART0->ISR;
  51. M0P_LPUART0->ICR = ~IRQ.ISR; // write 0 to clear interrupts
  52. // receive a ch
  53. if (IRQ.ISR_f.RC) {
  54. Lpuart0RxItf(M0P_LPUART0->SBUF);
  55. }
  56. if (IRQ.ISR_f.TXE & M0P_LPUART0->SCON_f.TXEIE) {
  57. #ifdef FINSH_TXBUF_DEPTH
  58. if (TxRaddr==TxWaddr){ // read FIFO to empty
  59. M0P_LPUART0->SCON_f.TXEIE = 0; // disable tx interrupt source
  60. } else {
  61. M0P_LPUART0->SBUF = (uint32_t)TxBuf[TxRaddr];
  62. level = rt_hw_interrupt_disable();
  63. if (TxRaddr>=(FINSH_TXBUF_DEPTH-1)){
  64. TxRaddr = 0;
  65. } else {
  66. TxRaddr++;
  67. }
  68. rt_hw_interrupt_enable(level);
  69. }
  70. #else
  71. M0P_LPUART0->SCON_f.TXEIE = 0; // disable tx interrupt source
  72. #endif
  73. }
  74. // CalExpireTime(120);
  75. }
  76. void lpuart0_tx_ch(char ch)
  77. {
  78. #ifdef FINSH_TXBUF_DEPTH
  79. // put a ch to TXBUF with nonblocking, drop it if almost full
  80. rt_base_t level;
  81. uint16_t used;
  82. while(1){
  83. used = TxWaddr - TxRaddr;
  84. if (TxWaddr<TxRaddr){
  85. used += FINSH_TXBUF_DEPTH;
  86. }
  87. if (used<(FINSH_TXBUF_DEPTH-1)){
  88. break;
  89. }
  90. }
  91. TxBuf[TxWaddr] = ch;
  92. level = rt_hw_interrupt_disable();
  93. if (TxWaddr>=(FINSH_TXBUF_DEPTH-1)){
  94. TxWaddr = 0;
  95. } else {
  96. TxWaddr++;
  97. }
  98. M0P_LPUART0->SCON_f.TXEIE = 1; // enable tx interrupt source
  99. #ifdef SLEEPDEEP_ENABLE
  100. SCB->SCR = (0x0<<SCB_SCR_SEVONPEND_Pos) |
  101. (0x0<<SCB_SCR_SLEEPDEEP_Pos) | // sleep
  102. (0x0<<SCB_SCR_SLEEPONEXIT_Pos);
  103. #endif
  104. rt_hw_interrupt_enable(level);
  105. return;
  106. #else
  107. // put a ch to TX data register directly, wait if not empty
  108. while (M0P_LPUART0->ISR_f.TXE==0) {
  109. // wait until TX empty
  110. }
  111. M0P_LPUART0->SBUF = (uint32_t)ch;
  112. //#ifdef SLEEPDEEP_ENABLE
  113. // // wait until TDR is moved to 32.768K clock domain
  114. // while (M0P_LPUART1->ISR_f.TXE==0) {
  115. // // wait until TX empty
  116. // }
  117. //#endif
  118. return;
  119. #endif
  120. }
  121. void lpuart0_tx_str(char *str)
  122. {
  123. char ch;
  124. uint32_t ClkEn;
  125. uint32_t ClkOff;
  126. #ifdef DEBUG_NB //WXL2026-5-20
  127. LOG("s:%s",str);
  128. #endif
  129. ClkEn = M0P_SYSCTRL->PERI_CLKEN0;
  130. ClkOff = (~ClkEn) & (1u<<PeriClk_LpUart0);
  131. if (ClkOff) {
  132. return;
  133. }
  134. while(1){
  135. ch = *str++;
  136. if (ch=='\0'){
  137. return;
  138. }
  139. // fow windows, line end is "\r\n"
  140. //if (ch=='\n'){
  141. // print_ch('\r');
  142. //}
  143. lpuart0_tx_ch(ch);
  144. }
  145. }