Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "scr1_csr_encoding.h"
- #include "riscv_csr_encoding.h"
- #include "mik32_memory_map.h"
- #include "power_manager.h"
- #include "pad_config.h"
- #include "epic.h"
- #include "uart.h"
- #include "mik32_hal_dma.h"
- #include "mik32_hal_timer32.h"
- #include "mik32_hal_irq.h"
- /*
- * Пример работы UART, когда прием и передача идет через ДМА, но у MIK32 нет циклического режима ДМА,
- * поэтому без прерываний не обойтись. Один канал ДМА - прием, перезапуск по прерыванию, второй канал ДМА -
- * передача, запуск по таймеру. Проблема в том, что когда буфер заполняется канал ДМА отключается и
- * между следующим запуском канала происходит потеря принимаемых данных. Поэтому данный вариант можно
- * использовать не всегда.
- * Когда этот вариант применим - когда передача пакетами в размер буфера с перерывами между пакетами,
- * чтобы ДМА успевал перезапускаться, либо пакетами в сумме кратными буферу, но тоже с разрывами на перезапуск ДМА.
- *
- */
- void DMA_Init(void);
- void DMA_CH0_Init(DMA_InitTypeDef *hdma);
- void DMA_CH1_Init(DMA_InitTypeDef *hdma);
- void Timer32_0_Init(void);
- DMA_InitTypeDef hdma;
- DMA_ChannelHandleTypeDef hdma_ch0;
- DMA_ChannelHandleTypeDef hdma_ch1;
- TIMER32_HandleTypeDef htimer32_0;
- #define BUFFER_SIZE 64
- volatile uint8_t buff[BUFFER_SIZE];
- void __attribute__((section(".ram_text"))) trap_handler(void)
- {
- static uint16_t old_pos = 0;
- if(EPIC_CHECK_DMA()){
- HAL_DMA_ClearIrq(&hdma);
- HAL_DMA_Start(&hdma_ch0, (void*)&UART_1->RXDATA, (void*)buff, BUFFER_SIZE-1);
- old_pos = 0;
- }
- if (EPIC_CHECK_TIMER32_0())
- {
- if ((TIMER32_0->INT_FLAGS & TIMER32_INT_OVERFLOW_M) & TIMER32_0->INT_MASK)
- {
- uint16_t pos = DMA_CONFIG->CHANNELS[0].LEN; //
- if (pos != old_pos) {
- if (pos > old_pos) {
- // данные подряд
- HAL_DMA_Start(&hdma_ch1, (void*)&buff[old_pos], (void*)&UART_1->TXDATA, pos - old_pos - 1);
- } else {
- // прием дошел до конца буфера и начал с начала, поэтому передаем от old_pos до конца, остальное
- // передадим со следующим прерыванием
- HAL_DMA_Start(&hdma_ch1, (void*)&buff[old_pos], (void*)&UART_1->TXDATA, BUFFER_SIZE - old_pos - 1);
- }
- old_pos = pos;
- }
- }
- TIMER32_0->INT_CLEAR = TIMER32_INTERRUPT_CLEAR_MASK;
- }
- //EPIC->CLEAR = 0xFFFFFFFF;
- }
- int main()
- {
- PM->CLK_APB_M_SET |= PM_CLOCK_APB_M_EPIC_M;
- PM->CLK_APB_P_SET |= PM_CLOCK_APB_P_UART_1_M | PM_CLOCK_APB_P_GPIO_1_M ;
- PAD_CONFIG->PORT_1_CFG = (PAD_CONFIG->PORT_1_CFG & ~(PAD_CONFIG_PIN_M(8) | PAD_CONFIG_PIN_M(9))) \
- | PAD_CONFIG_PIN(8,0x01) | PAD_CONFIG_PIN(9,0x01);
- UART_1->CONTROL1 = 0;
- UART_1->DIVIDER = 32000000/115200; // скорость 115200
- UART_1->CONTROL2 = 0;
- UART_1->CONTROL3 = UART_CONTROL3_DMAR_M | UART_CONTROL3_DMAT_M;
- UART_1->CONTROL1 = UART_CONTROL1_TE_M | UART_CONTROL1_RE_M | UART_CONTROL1_M_8BIT_M | UART_CONTROL1_UE_M;
- Timer32_0_Init();
- HAL_EPIC_MaskLevelSet(HAL_EPIC_TIMER32_0_MASK);
- /* Запуск таймера и прерываний в продолжительном режиме */
- HAL_Timer32_Start_IT(&htimer32_0, TIMER32_INT_OVERFLOW_M);
- DMA_Init();
- HAL_DMA_Start(&hdma_ch0, (void*)&UART_1->RXDATA, (void*)buff, BUFFER_SIZE-1);
- // global interrupt enable
- set_csr(mstatus, MSTATUS_MIE); // Global interrupt enable
- set_csr(mie, MIE_MEIE); // Machine External Interrupt Enable
- while (1)
- {
- }
- }
- void DMA_Init(void)
- {
- /* Настройки DMA */
- hdma.Instance = DMA_CONFIG;
- hdma.CurrentValue = DMA_CURRENT_VALUE_ENABLE;
- HAL_DMA_Init(&hdma);
- HAL_DMA_GlobalIRQEnable(&hdma, DMA_IRQ_ENABLE);
- /* Инициализация канала */
- DMA_CH0_Init(&hdma);
- DMA_CH1_Init(&hdma);
- HAL_DMA_LocalIRQEnable(&hdma_ch0, DMA_IRQ_ENABLE);
- }
- void DMA_CH0_Init(DMA_InitTypeDef *hdma)
- {
- hdma_ch0.dma = hdma;
- /* Настройки канала */
- hdma_ch0.ChannelInit.Channel = DMA_CHANNEL_0;
- hdma_ch0.ChannelInit.Priority = DMA_CHANNEL_PRIORITY_VERY_HIGH;
- hdma_ch0.ChannelInit.ReadMode = DMA_CHANNEL_MODE_PERIPHERY;
- hdma_ch0.ChannelInit.ReadInc = DMA_CHANNEL_INC_DISABLE;
- hdma_ch0.ChannelInit.ReadSize = DMA_CHANNEL_SIZE_BYTE; /* data_len должно быть кратно read_size */
- hdma_ch0.ChannelInit.ReadBurstSize = 0; /* read_burst_size должно быть кратно read_size */
- hdma_ch0.ChannelInit.ReadRequest = DMA_CHANNEL_USART_1_REQUEST;
- hdma_ch0.ChannelInit.ReadAck = DMA_CHANNEL_ACK_ENABLE;
- hdma_ch0.ChannelInit.WriteMode = DMA_CHANNEL_MODE_MEMORY;
- hdma_ch0.ChannelInit.WriteInc = DMA_CHANNEL_INC_ENABLE;
- hdma_ch0.ChannelInit.WriteSize = DMA_CHANNEL_SIZE_BYTE; /* data_len должно быть кратно write_size */
- hdma_ch0.ChannelInit.WriteBurstSize = 0; /* write_burst_size должно быть кратно read_size */
- hdma_ch0.ChannelInit.WriteRequest = DMA_CHANNEL_USART_1_REQUEST;
- hdma_ch0.ChannelInit.WriteAck = DMA_CHANNEL_ACK_ENABLE;
- }
- void DMA_CH1_Init(DMA_InitTypeDef *hdma)
- {
- hdma_ch1.dma = hdma;
- /* Настройки канала */
- hdma_ch1.ChannelInit.Channel = DMA_CHANNEL_1;
- hdma_ch1.ChannelInit.Priority = DMA_CHANNEL_PRIORITY_HIGH;
- hdma_ch1.ChannelInit.ReadMode = DMA_CHANNEL_MODE_MEMORY;
- hdma_ch1.ChannelInit.ReadInc = DMA_CHANNEL_INC_ENABLE;
- hdma_ch1.ChannelInit.ReadSize = DMA_CHANNEL_SIZE_BYTE; /* data_len должно быть кратно read_size */
- hdma_ch1.ChannelInit.ReadBurstSize = 0; /* read_burst_size должно быть кратно read_size */
- hdma_ch1.ChannelInit.ReadRequest = DMA_CHANNEL_USART_1_REQUEST;
- hdma_ch1.ChannelInit.ReadAck = DMA_CHANNEL_ACK_ENABLE;
- hdma_ch1.ChannelInit.WriteMode = DMA_CHANNEL_MODE_PERIPHERY;
- hdma_ch1.ChannelInit.WriteInc = DMA_CHANNEL_INC_DISABLE;
- hdma_ch1.ChannelInit.WriteSize = DMA_CHANNEL_SIZE_BYTE; /* data_len должно быть кратно write_size */
- hdma_ch1.ChannelInit.WriteBurstSize = 0; /* write_burst_size должно быть кратно read_size */
- hdma_ch1.ChannelInit.WriteRequest = DMA_CHANNEL_USART_1_REQUEST;
- hdma_ch1.ChannelInit.WriteAck = DMA_CHANNEL_ACK_ENABLE;
- }
- void Timer32_0_Init(void)
- {
- htimer32_0.Instance = TIMER32_0;
- htimer32_0.Top = 320000;
- htimer32_0.Clock.Source = TIMER32_SOURCE_PRESCALER;
- htimer32_0.Clock.Prescaler = 0;
- htimer32_0.InterruptMask = TIMER32_INT_OVERFLOW_M;
- htimer32_0.CountMode = TIMER32_COUNTMODE_FORWARD;
- HAL_Timer32_Init(&htimer32_0);
- }
Advertisement
Add Comment
Please, Sign In to add comment