petrdynin

Mik32+UART+DMA_RX_&_DMA_TX

Sep 26th, 2025 (edited)
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.21 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. #include "mik32_hal_dma.h"
  9. #include "mik32_hal_timer32.h"
  10. #include "mik32_hal_irq.h"
  11.  
  12.  
  13. /*
  14. * Пример работы UART, когда прием и передача идет через ДМА, но у MIK32 нет циклического режима ДМА,
  15. * поэтому без прерываний не обойтись. Один канал ДМА - прием, перезапуск по прерыванию, второй канал ДМА -
  16. * передача, запуск по таймеру. Проблема в том, что когда буфер заполняется канал ДМА отключается и
  17. * между следующим запуском  канала происходит потеря принимаемых данных. Поэтому данный вариант можно
  18. * использовать не всегда.
  19. * Когда этот вариант применим - когда передача пакетами в размер буфера с перерывами между пакетами,
  20. * чтобы ДМА успевал перезапускаться, либо пакетами в сумме кратными буферу, но тоже с разрывами на перезапуск ДМА.
  21. *
  22. */
  23.  
  24.  
  25. void DMA_Init(void);
  26. void DMA_CH0_Init(DMA_InitTypeDef *hdma);
  27. void DMA_CH1_Init(DMA_InitTypeDef *hdma);
  28. void Timer32_0_Init(void);
  29.  
  30. DMA_InitTypeDef hdma;
  31. DMA_ChannelHandleTypeDef hdma_ch0;
  32. DMA_ChannelHandleTypeDef hdma_ch1;
  33. TIMER32_HandleTypeDef htimer32_0;
  34.  
  35. #define BUFFER_SIZE 64
  36.  
  37.  
  38. volatile uint8_t buff[BUFFER_SIZE];
  39.  
  40. void __attribute__((section(".ram_text"))) trap_handler(void)
  41. {
  42.     static uint16_t old_pos = 0;
  43.  
  44.     if(EPIC_CHECK_DMA()){
  45.        HAL_DMA_ClearIrq(&hdma);
  46.        HAL_DMA_Start(&hdma_ch0, (void*)&UART_1->RXDATA, (void*)buff, BUFFER_SIZE-1);
  47.        old_pos = 0;
  48.  
  49.     }
  50.  
  51.     if (EPIC_CHECK_TIMER32_0())
  52.         {
  53.  
  54.             if ((TIMER32_0->INT_FLAGS & TIMER32_INT_OVERFLOW_M) & TIMER32_0->INT_MASK)
  55.               {
  56.                 uint16_t pos = DMA_CONFIG->CHANNELS[0].LEN; //
  57.  
  58.                 if (pos != old_pos) {
  59.                     if (pos > old_pos) {
  60.                        // данные подряд
  61.                        HAL_DMA_Start(&hdma_ch1, (void*)&buff[old_pos], (void*)&UART_1->TXDATA, pos - old_pos - 1);
  62.                     } else {
  63.                         // прием дошел до конца буфера и начал с начала, поэтому передаем от old_pos до конца, остальное
  64.                         // передадим со следующим прерыванием
  65.                         HAL_DMA_Start(&hdma_ch1, (void*)&buff[old_pos], (void*)&UART_1->TXDATA, BUFFER_SIZE - old_pos - 1);
  66.                     }
  67.                     old_pos = pos;
  68.                 }
  69.             }
  70.  
  71.           TIMER32_0->INT_CLEAR = TIMER32_INTERRUPT_CLEAR_MASK;
  72.         }
  73.  
  74.   //EPIC->CLEAR = 0xFFFFFFFF;
  75.  
  76. }
  77.  
  78.  
  79. int main()
  80. {
  81.  
  82.     PM->CLK_APB_M_SET |= PM_CLOCK_APB_M_EPIC_M;
  83.     PM->CLK_APB_P_SET |= PM_CLOCK_APB_P_UART_1_M | PM_CLOCK_APB_P_GPIO_1_M ;
  84.  
  85.     PAD_CONFIG->PORT_1_CFG  = (PAD_CONFIG->PORT_1_CFG  & ~(PAD_CONFIG_PIN_M(8) | PAD_CONFIG_PIN_M(9))) \
  86.                                | PAD_CONFIG_PIN(8,0x01) | PAD_CONFIG_PIN(9,0x01);
  87.  
  88.     UART_1->CONTROL1 = 0;
  89.     UART_1->DIVIDER  = 32000000/115200;  // скорость 115200
  90.     UART_1->CONTROL2 = 0;
  91.     UART_1->CONTROL3 = UART_CONTROL3_DMAR_M | UART_CONTROL3_DMAT_M;
  92.     UART_1->CONTROL1 = UART_CONTROL1_TE_M | UART_CONTROL1_RE_M | UART_CONTROL1_M_8BIT_M | UART_CONTROL1_UE_M;
  93.  
  94.     Timer32_0_Init();
  95.     HAL_EPIC_MaskLevelSet(HAL_EPIC_TIMER32_0_MASK);
  96.     /* Запуск таймера и прерываний в продолжительном режиме */
  97.     HAL_Timer32_Start_IT(&htimer32_0, TIMER32_INT_OVERFLOW_M);
  98.     DMA_Init();
  99.     HAL_DMA_Start(&hdma_ch0, (void*)&UART_1->RXDATA, (void*)buff, BUFFER_SIZE-1);
  100.     // global interrupt enable
  101.     set_csr(mstatus, MSTATUS_MIE);  // Global interrupt enable
  102.     set_csr(mie, MIE_MEIE);         // Machine External Interrupt Enable
  103.  
  104.     while (1)
  105.     {
  106.  
  107.  
  108.  
  109.     }
  110. }
  111.  
  112.  
  113. void DMA_Init(void)
  114. {
  115.  
  116.     /* Настройки DMA */
  117.     hdma.Instance = DMA_CONFIG;
  118.     hdma.CurrentValue = DMA_CURRENT_VALUE_ENABLE;
  119.     HAL_DMA_Init(&hdma);
  120.     HAL_DMA_GlobalIRQEnable(&hdma, DMA_IRQ_ENABLE);
  121.     /* Инициализация канала */
  122.     DMA_CH0_Init(&hdma);
  123.     DMA_CH1_Init(&hdma);
  124.     HAL_DMA_LocalIRQEnable(&hdma_ch0, DMA_IRQ_ENABLE);
  125. }
  126.  
  127. void DMA_CH0_Init(DMA_InitTypeDef *hdma)
  128. {
  129.     hdma_ch0.dma = hdma;
  130.  
  131.     /* Настройки канала */
  132.     hdma_ch0.ChannelInit.Channel = DMA_CHANNEL_0;
  133.     hdma_ch0.ChannelInit.Priority = DMA_CHANNEL_PRIORITY_VERY_HIGH;
  134.  
  135.     hdma_ch0.ChannelInit.ReadMode = DMA_CHANNEL_MODE_PERIPHERY;
  136.     hdma_ch0.ChannelInit.ReadInc = DMA_CHANNEL_INC_DISABLE;
  137.     hdma_ch0.ChannelInit.ReadSize = DMA_CHANNEL_SIZE_BYTE; /* data_len должно быть кратно read_size */
  138.     hdma_ch0.ChannelInit.ReadBurstSize = 0;                    /* read_burst_size должно быть кратно read_size */
  139.     hdma_ch0.ChannelInit.ReadRequest = DMA_CHANNEL_USART_1_REQUEST;
  140.     hdma_ch0.ChannelInit.ReadAck = DMA_CHANNEL_ACK_ENABLE;
  141.  
  142.     hdma_ch0.ChannelInit.WriteMode = DMA_CHANNEL_MODE_MEMORY;
  143.     hdma_ch0.ChannelInit.WriteInc = DMA_CHANNEL_INC_ENABLE;
  144.     hdma_ch0.ChannelInit.WriteSize = DMA_CHANNEL_SIZE_BYTE; /* data_len должно быть кратно write_size */
  145.     hdma_ch0.ChannelInit.WriteBurstSize = 0;                /* write_burst_size должно быть кратно read_size */
  146.     hdma_ch0.ChannelInit.WriteRequest = DMA_CHANNEL_USART_1_REQUEST;
  147.     hdma_ch0.ChannelInit.WriteAck = DMA_CHANNEL_ACK_ENABLE;
  148. }
  149.  
  150. void DMA_CH1_Init(DMA_InitTypeDef *hdma)
  151. {
  152.     hdma_ch1.dma = hdma;
  153.  
  154.     /* Настройки канала */
  155.     hdma_ch1.ChannelInit.Channel = DMA_CHANNEL_1;
  156.     hdma_ch1.ChannelInit.Priority = DMA_CHANNEL_PRIORITY_HIGH;
  157.  
  158.     hdma_ch1.ChannelInit.ReadMode = DMA_CHANNEL_MODE_MEMORY;
  159.     hdma_ch1.ChannelInit.ReadInc = DMA_CHANNEL_INC_ENABLE;
  160.     hdma_ch1.ChannelInit.ReadSize = DMA_CHANNEL_SIZE_BYTE; /* data_len должно быть кратно read_size */
  161.     hdma_ch1.ChannelInit.ReadBurstSize = 0;                    /* read_burst_size должно быть кратно read_size */
  162.     hdma_ch1.ChannelInit.ReadRequest = DMA_CHANNEL_USART_1_REQUEST;
  163.     hdma_ch1.ChannelInit.ReadAck = DMA_CHANNEL_ACK_ENABLE;
  164.  
  165.     hdma_ch1.ChannelInit.WriteMode = DMA_CHANNEL_MODE_PERIPHERY;
  166.     hdma_ch1.ChannelInit.WriteInc = DMA_CHANNEL_INC_DISABLE;
  167.     hdma_ch1.ChannelInit.WriteSize = DMA_CHANNEL_SIZE_BYTE; /* data_len должно быть кратно write_size */
  168.     hdma_ch1.ChannelInit.WriteBurstSize = 0;                /* write_burst_size должно быть кратно read_size */
  169.     hdma_ch1.ChannelInit.WriteRequest = DMA_CHANNEL_USART_1_REQUEST;
  170.     hdma_ch1.ChannelInit.WriteAck = DMA_CHANNEL_ACK_ENABLE;
  171. }
  172.  
  173.  
  174. void Timer32_0_Init(void)
  175. {
  176.     htimer32_0.Instance = TIMER32_0;
  177.     htimer32_0.Top = 320000;
  178.     htimer32_0.Clock.Source = TIMER32_SOURCE_PRESCALER;
  179.     htimer32_0.Clock.Prescaler = 0;
  180.     htimer32_0.InterruptMask = TIMER32_INT_OVERFLOW_M;
  181.     htimer32_0.CountMode = TIMER32_COUNTMODE_FORWARD;
  182.     HAL_Timer32_Init(&htimer32_0);
  183. }
  184.  
Advertisement
Add Comment
Please, Sign In to add comment