petrdynin

Mik32+UART1+IRQ+CircBuffer

Sep 28th, 2025 (edited)
270
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.67 KB | Source Code | 0 0
  1. #include "scr1_csr_encoding.h"
  2. #include "riscv_csr_encoding.h"
  3. #include "mik32_memory_map.h"
  4. #include "power_manager.h"
  5. #include "pad_config.h"
  6. #include "epic.h"
  7. #include "uart.h"
  8.  
  9. /*
  10. * Пример работы UART с прерываниями, данные поступают в кольцевой буфер
  11. * откуда забираются и отправляются обратно (режим эхо).
  12. */
  13.  
  14. #define __disable_irq()     __asm volatile("csrc mstatus, 8" )
  15. #define __enable_irq()      __asm volatile("csrs mstatus, 8" )
  16.  
  17. void uart1_initialize(uint32_t baud);
  18. uint8_t uart1_test(void);
  19. uint16_t uart1_getc(void);
  20. void uart1_putc(uint16_t d);
  21.  
  22. #define BUFFER_SIZE 64
  23.  
  24. typedef struct {
  25.     uint8_t     ri, wi, ct;             // Read index, Write index, Data counter
  26.     uint16_t    buff[BUFFER_SIZE];      // FIFO buffer
  27. }FIFO;
  28.  
  29. volatile FIFO TxFifo_1, RxFifo_1;
  30.  
  31. void __attribute__((section(".ram_text"))) trap_handler(void)
  32. {
  33.     if (EPIC->RAW_STATUS & (1<<EPIC_UART_1_INDEX))  {
  34.  
  35.             if(UART_1->FLAGS & UART_FLAGS_RXNE_M)
  36.                   {
  37.                       uint16_t d = UART_1->RXDATA;
  38.                       uint8_t i = RxFifo_1.ct;
  39.                       if(i < BUFFER_SIZE) {
  40.                          RxFifo_1.ct = ++i;
  41.                          i = RxFifo_1.wi;
  42.                          RxFifo_1.buff[i++] = d;
  43.                          RxFifo_1.wi = i % BUFFER_SIZE;
  44.                         }
  45.                   }
  46.  
  47.             if(UART_1->FLAGS & UART_FLAGS_TC_M){
  48.                uint8_t ii = TxFifo_1.ct;
  49.                if(ii){
  50.                        TxFifo_1.ct = --ii;
  51.                        ii = TxFifo_1.ri;
  52.                        UART_1->TXDATA = TxFifo_1.buff[ii++];
  53.                        TxFifo_1.ri = ii % BUFFER_SIZE;
  54.                    }
  55.                else {
  56.                        UART_1->CONTROL1 &= ~UART_CONTROL1_TCIE_M;
  57.                     }
  58.              }
  59.          }
  60. }
  61.  
  62.  
  63. int main()
  64. {
  65.     PM->CLK_APB_M_SET |= PM_CLOCK_APB_M_EPIC_M;
  66.  
  67.     uart1_initialize(115200);
  68.  
  69.     set_csr(mstatus, MSTATUS_MIE);
  70.     set_csr(mie, MIE_MEIE);
  71.  
  72.     while (1)
  73.     {
  74.  
  75.         if(uart1_test()){
  76.             uart1_putc(uart1_getc());
  77.         }
  78.  
  79.     }
  80. }
  81.  
  82.  
  83. void uart1_initialize(uint32_t baud)
  84.  {
  85.     uint8_t ready;
  86.  
  87.     PM->CLK_APB_P_SET |= PM_CLOCK_APB_P_UART_1_M | PM_CLOCK_APB_P_GPIO_1_M ;
  88.  
  89.     UART_1->CONTROL1 = 0;
  90.     UART_1->DIVIDER  = 32000000/baud;
  91.     UART_1->FLAGS    = 0xFFFFFFFF;
  92.  
  93.     UART_1->CONTROL2 = 0;
  94.     UART_1->CONTROL3 = 0;
  95.     UART_1->CONTROL1 = UART_CONTROL1_TE_M | UART_CONTROL1_RE_M | UART_CONTROL1_M_8BIT_M | UART_CONTROL1_UE_M;
  96.  
  97.     do
  98.       {
  99.         uint32_t flags = UART_1->FLAGS;
  100.         ready = 1;
  101.         if(UART_1->CONTROL1 & UART_CONTROL1_RE_M)
  102.            {
  103.               ready = ready && ((flags & UART_FLAGS_REACK_M) != 0);
  104.            }
  105.         if(UART_1->CONTROL1 & UART_CONTROL1_TE_M)
  106.            {
  107.               ready = ready && ((flags & UART_FLAGS_TEACK_M) != 0);
  108.            }
  109.       }while (!ready);
  110.  /*************************************************************************************************************************/
  111.      UART_1->TXDATA = 'A';      // это нужно для взведения флагов TC и TXE, чтобы при разрешении прерывания оно сразу и сработало.
  112.                                 // идея в том чтобы первый байт умер внутри, не дойдя до выводов, а флаги взвелись
  113.      while(!(UART_1->FLAGS & UART_FLAGS_TC_M));
  114.      PAD_CONFIG->PORT_1_CFG  = (PAD_CONFIG->PORT_1_CFG  & ~(PAD_CONFIG_PIN_M(8) | PAD_CONFIG_PIN_M(9))) \
  115.                                | PAD_CONFIG_PIN(8,0x01) | PAD_CONFIG_PIN(9,0x01);
  116.      /*************************************************************************************************************************/
  117.      TxFifo_1.ri = 0; TxFifo_1.wi = 0; TxFifo_1.ct = 0;
  118.      RxFifo_1.ri = 0; RxFifo_1.wi = 0; RxFifo_1.ct = 0;
  119.  
  120.      EPIC->MASK_LEVEL_SET |= 1 << EPIC_UART_1_INDEX;
  121.  
  122.      UART_1->CONTROL1 |= UART_CONTROL1_RXNEIE_M;
  123.  
  124.  }
  125.  
  126.  
  127. uint8_t  uart1_test (void)
  128. {
  129.     return RxFifo_1.ct;
  130. }
  131.  
  132. uint16_t uart1_getc (void)
  133. {
  134.     uint16_t     d;
  135.     uint16_t i;
  136.  
  137.     while (!RxFifo_1.ct) ;          // Wait while Rx FIFO empty
  138.  
  139.     i = RxFifo_1.ri;                // Get a byte from Rx FIFO
  140.     d = RxFifo_1.buff[i++];
  141.     RxFifo_1.ri = i % BUFFER_SIZE;
  142.     __disable_irq();
  143.     RxFifo_1.ct--;
  144.     __enable_irq();
  145.  
  146.     return d;
  147. }
  148.  
  149. void uart1_putc (uint16_t d)
  150. {
  151.     uint16_t     i;
  152.  
  153.     while (TxFifo_1.ct >= BUFFER_SIZE);      //* Wait while Tx FIFO is full
  154.     __disable_irq();
  155.     i = TxFifo_1.wi;                         //* Put a data into the Tx FIFO
  156.     TxFifo_1.buff[i++] = d;
  157.     TxFifo_1.wi = i % BUFFER_SIZE;
  158.     TxFifo_1.ct++;
  159.     if(!(UART_1->CONTROL1 & UART_CONTROL1_TCIE_M)) //If transmission sequense is not running, start the tx sequense
  160.     {
  161.         UART_1->CONTROL1 |= UART_CONTROL1_TCIE_M;
  162.     }
  163.     __enable_irq();
  164. }
  165.  
Advertisement
Add Comment
Please, Sign In to add comment