#include "iostm8l051f3.h" #include "Driver_DMA.hpp" char UartBuffer[128]; // DMA DriverDMA<EnumDMA::DMA1,EnumDMA::CHANNEL1> DMAChannelTX; // DMA1 1 DriverDMA<EnumDMA::DMA1,EnumDMA::CHANNEL2> DMAChannelRX; // DMA1 2 void func() { DMAChannelTX.global_disable(); // // DMA DMAChannelTX.set_periph_addr(&USART1_DR); // DMAChannelTX.set_memory0_addr(UartBuffer); // DMAChannelTX = EnumDMA::DATABLOCK_8bit; // - DMAChannelTX = EnumDMA::PRIORITY_MEDIUM; // DMAChannelTX = EnumDMA::MEMPNT_INCREMENT; // DMAChannelTX = EnumDMA::MEMORY_TO_PHERIPH; // UART DMAChannelTX = EnumDMA::CIRCULAR_DISABLE; // // DMA DMAChannelRX.set_periph_addr(&USART1_DR); DMAChannelRX.set_memory0_addr(UartBuffer); DMAChannelRX = EnumDMA::DATABLOCK_8bit; DMAChannelRX = EnumDMA::PRIORITY_MEDIUM; DMAChannelRX = EnumDMA::MEMPNT_INCREMENT; DMAChannelRX = EnumDMA::PHERIPH_TO_MEMORY; // UART DMAChannelRX = EnumDMA::CIRCULAR_DISABLE; DMAChannelRX.set_number_of_transfers(sizeof(UartBuffer)); DMAChannelRX.channel_enable(); // DMAChannelTX.global_enable(); // }
struct EnumDMA { enum DMASel{ DMA1 = 0x5070 }; enum ChannelSel{ CHANNEL0 = 0x05, CHANNEL1 = 0x0F, CHANNEL2 = 0x19, CHANNEL3 = 0x23 }; enum DataBlock{ DATABLOCK_8bit, DATABLOCK_16bit }; enum ChannelPriority{ PRIORITY_LOW, PRIORITY_MEDIUM, PRIORITY_HIGH, PRIORITY_VERYHIGH }; enum MemoryPointerMode{ MEMPNT_DECREMENT, MEMPNT_INCREMENT }; enum CircularBufferMode{ CIRCULAR_DISABLE, CIRCULAR_ENABLE }; enum TransferType{ // 3 TRANS_TYPE_PHERIPH_TO_MEMORY, TRANS_TYPE_MEMORY0_TO_MEMORY1 }; enum TransferDirection{ PHERIPH_TO_MEMORY, MEMORY_TO_PHERIPH }; enum InterruptSelection{ INTERRUPT_HALF_TRANSACTION_COMPLETE, INTERRUPT_TRANSACTION_COMPLETE }; enum InterruptVectors{ VECTOR_DMA1_CHANNEL0_HALF_TRANSACTION_COMPLETE = DMA1_CH0_HT_vector, VECTOR_DMA1_CHANNEL0_TRANSACTION_COMPLETE = DMA1_CH0_TC_vector, VECTOR_DMA1_CHANNEL1_HALF_TRANSACTION_COMPLETE = DMA1_CH1_HT_vector, VECTOR_DMA1_CHANNEL1_TRANSACTION_COMPLETE = DMA1_CH1_TC_vector, VECTOR_DMA1_CHANNEL2_HALF_TRANSACTION_COMPLETE = DMA1_CH2_HT_vector, VECTOR_DMA1_CHANNEL2_TRANSACTION_COMPLETE = DMA1_CH2_TC_vector, VECTOR_DMA1_CHANNEL3_HALF_TRANSACTION_COMPLETE = DMA1_CH3_HT_vector, VECTOR_DMA1_CHANNEL3_TRANSACTION_COMPLETE = DMA1_CH3_TC_vector, }; };
template <EnumDMA::DMASel DMA, EnumDMA::ChannelSel DMAChannel> class DriverDMA { private: ... struct DMA_struct // DMA { volatile GCSR_REG GCSR; /*!< Global configuration and status register */ volatile GIR_REG GIR1; /*!< Global interrupt register 1 */ }; ... struct DMA_Channel_struct // DMA { volatile CCR_REG CCR; /*!< CHx Control register */ volatile CSPR_REG CSPR; /*!< CHx Status & Priority register */ volatile unsigned char CNDTR; /*!< CHx Number of Bytes to Tranfer register */ volatile unsigned char CPARH; /*!< Peripheral Address High register */ volatile unsigned char CPARL; /*!< Peripheral Address Low register */ volatile unsigned char CM0EAR; /*!< Memory 0 Extended Address register (for channel3)*/ volatile unsigned char CM0ARH; /*!< Memory 0 Address High register */ volatile unsigned char CM0ARL; /*!< Memory 0 Address Low register */ }; u8 number_of_transfers; u8 NumChannel; public: DriverDMA(); void operator= (EnumDMA::DataBlock); void operator= (EnumDMA::ChannelPriority); void operator= (EnumDMA::MemoryPointerMode); void operator= (EnumDMA::CircularBufferMode); void operator= (EnumDMA::TransferDirection); void operator= (EnumDMA::TransferType); // 3 void global_enable(); void global_disable(); void channel_enable(); void channel_disable(); void set_number_of_transfers(const u16 trans_num); void set_periph_addr(u8 volatile* addr); void set_memory0_addr(u8* addr); // 00000 01FFF void set_memory1_addr(u8* addr); // 3 bool is_busy(); u16 get_amount_of_last_transation(); void interrupt_enable(EnumDMA::InterruptSelection); void interrupt_disable(EnumDMA::InterruptSelection); void interrupt_clear_pending_flag(EnumDMA::InterruptSelection); };
//---------------------------------------------------------------------------------------------- template <EnumDMA::DMASel DMA, EnumDMA::ChannelSel DMAChannel> DriverDMA<DMA,DMAChannel>::DriverDMA() { CLK_PCKENR2_bit.PCKEN24 = 1; // DMA clock enable __DMA->GCSR.bit.TO = 31; NumChannel = (u8)DMAChannel; } //---------------------------------------------------------------------------------------------- template <EnumDMA::DMASel DMA, EnumDMA::ChannelSel DMAChannel> void DriverDMA<DMA,DMAChannel>::operator= (EnumDMA::DataBlock db) { __DMACHANNEL->CSPR.bit.TSIZE = db; } //---------------------------------------------------------------------------------------------- template <EnumDMA::DMASel DMA, EnumDMA::ChannelSel DMAChannel> void DriverDMA<DMA,DMAChannel>::global_enable() { __DMA->GCSR.bit.GEN = 1; // Global enable of DMA1 }
#define __DMA ((DMA_struct*) DMA) #define __DMACHANNEL ((DMA_Channel_struct*) ((u32)DMA + (u32)DMAChannel))
__DMACHANNEL->CSPR.bit.TSIZE = db;
__DMA->GCSR.bit.GEN = 1;
void func() { // DMAChannelTX.interrupt_enable(EnumDMA::INTERRUPT_TRANSACTION_COMPLETE) } #pragma vector = EnumDMA::VECTOR_DMA1_CHANNEL1_TRANSACTION_COMPLETE __interrupt void DMA_transaction_complete() { // DMAChannelTX.interrupt_clear_pending_flag(EnumDMA::INTERRUPT_TRANSACTION_COMPLETE) }
class DriverUART { private: ... u8 UartBuffer[128]; DriverDMA<EnumDMA::DMA1,EnumDMA::CHANNEL1> DMAChannelTX; DriverDMA<EnumDMA::DMA1,EnumDMA::CHANNEL2> DMAChannelRX; ...
//----------------------------------------------------------------------- // Main DriverUART Constructor //----------------------------------------------------------------------- DriverUART::DriverUART(SELECTUART uart, u32 baud_rate, u32 sys_clock, PinconfigUART confPin) { CLK_PCKENR1_bit.PCKEN15 = 1; // UART clock enable USART1_CR1_bit.USARTD = 0; USART1_CR5_bit.DMAT = 1; // DMA enable transmitter USART1_CR5_bit.DMAR = 1; // DMA enable receiver DMAChannelTX.global_disable(); DMAChannelTX.set_periph_addr(&USART1_DR); DMAChannelTX.set_memory0_addr(UartBuffer); DMAChannelTX = EnumDMA::DATABLOCK_8bit; DMAChannelTX = EnumDMA::PRIORITY_MEDIUM; DMAChannelTX = EnumDMA::MEMPNT_INCREMENT; DMAChannelTX = EnumDMA::MEMORY_TO_PHERIPH; DMAChannelTX = EnumDMA::CIRCULAR_DISABLE; DMAChannelRX.set_periph_addr(&USART1_DR); DMAChannelRX.set_memory0_addr(UartBuffer); DMAChannelRX = EnumDMA::DATABLOCK_8bit; DMAChannelRX = EnumDMA::PRIORITY_MEDIUM; DMAChannelRX = EnumDMA::MEMPNT_INCREMENT; DMAChannelRX = EnumDMA::PHERIPH_TO_MEMORY; DMAChannelRX = EnumDMA::CIRCULAR_DISABLE; DMAChannelRX.set_number_of_transfers(sizeof(UartBuffer)); DMAChannelRX.channel_enable(); DMAChannelTX.global_enable(); set_sysclock(sys_clock, baud_rate); USART1_CR2_bit.TCIEN = 1; // . USART1_CR2_bit.ILIEN = 1; // . USART1_CR5_bit.EIE = 1; // . __enable_interrupt(); close(); }
void DriverUART::transmit(u8 * source, u16 size) { while(DMAChannelTX.is_busy()) ; select_direction(TRANSMITION); __disable_interrupt(); DMAChannelTX.global_disable(); DMAChannelTX.channel_disable(); DMAChannelTX.set_number_of_transfers(size); DMAChannelTX.set_memory0_addr(source); DMAChannelTX.global_enable(); DMAChannelTX.channel_enable(); __enable_interrupt(); }
u8 buffer[] = "hello world!" Uart1.transmit(buffer, sizeof(buffer));
void DriverUART::reception_handshake() { __disable_interrupt(); DMAChannelRX.global_disable(); DMAChannelRX.channel_disable(); received_size = DMAChannelRX.get_amount_of_last_transation(); DMAChannelRX.set_number_of_transfers(sizeof(UartBuffer)); DMAChannelRX.global_enable(); DMAChannelRX.channel_enable(); __enable_interrupt(); }
//-------------------------------------------------------------------------- // //-------------------------------------------------------------------------- void DriverUART::receive_handle() { u16 size; u8* pnt; Uart1.reception_handshake(); size = Uart1.get_received_size(); pnt = Uart1.get_pointer_on_internal_buffer(); // }
Source: https://habr.com/ru/post/225635/
All Articles