Skip to content

Commit

Permalink
DMA for STM32F4/F7, still not working...
Browse files Browse the repository at this point in the history
  • Loading branch information
rleh committed Oct 26, 2021
1 parent 9afb78c commit e8f2aa4
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 65 deletions.
86 changes: 64 additions & 22 deletions examples/nucleo_f429zi/spi_dma/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
// ----------------------------------------------------------------------------

#include <modm/board.hpp>
#include <modm/processing.hpp>

using Mosi = GpioOutputB5;
using Miso = GpioInputB4;
Expand All @@ -19,38 +20,79 @@ using DmaTx = Dma2::Channel3;
using Spi = SpiMaster1_Dma<DmaRx, DmaTx>;
//using Spi = SpiMaster1;

uint8_t sendBuffer[13] { "data to send" };
uint8_t receiveBuffer[13];

int main()
class SpiThread : public modm::pt::Protothread
{
Board::initialize();
public:

MODM_LOG_INFO << "Hello from SPI-DMA example on Nucleo-F429ZI!" << modm::endl;
bool
update()
{
PT_BEGIN();

// Enable DMA1 controller
Dma2::enable();
// Enable SPI1
Spi::connect<Mosi::Mosi, Miso::Miso, Sck::Sck>();
Spi::initialize<Board::SystemClock, 10_MHz>();
// Enable DMA controller
Dma2::enable();

while (true)
{
MODM_LOG_INFO << "sendBuffer adress: " << modm::hex << sendBuffer << modm::endl;
MODM_LOG_INFO << "receiveBuffer adress: " << modm::hex << receiveBuffer << modm::endl;
MODM_LOG_INFO << "Info: 0x20000000 is start of SRAM1" << modm::endl;
// Enable and initialize SPI
Spi::connect<Mosi::Mosi, Miso::Miso, Sck::Sck>();
Spi::initialize<Board::SystemClock, 10_MHz>();

MODM_LOG_INFO << "Before first transfer" << modm::endl;
while (true)
{
MODM_LOG_INFO << "sendBuffer adress: " << modm::hex << sendBuffer << modm::endl;
MODM_LOG_INFO << "receiveBuffer adress: " << modm::hex << receiveBuffer << modm::endl;
MODM_LOG_INFO << "Info: 0x20000000 is start of SRAM1" << modm::endl;

// send out 12 bytes, don't care about response
Spi::transferBlocking(sendBuffer, nullptr, 12);
MODM_LOG_INFO << "Before first transfer" << modm::endl;

MODM_LOG_INFO << "After first transfer" << modm::endl;
// send out 12 bytes, don't care about response
PT_CALL(Spi::transfer(sendBuffer, nullptr, 12));

MODM_LOG_INFO << "After first transfer" << modm::endl;

// send out 12 bytes, read in 12 bytes
PT_CALL(Spi::transfer(sendBuffer, receiveBuffer, 12));

MODM_LOG_INFO << "After second transfer" << modm::endl << modm::endl;
}

PT_END();
}

// send out 12 bytes, read in 12 bytes
Spi::transferBlocking(sendBuffer, receiveBuffer, 12);
private:
uint8_t sendBuffer[13] { "data to send" };
uint8_t receiveBuffer[13];
};

MODM_LOG_INFO << "After second transfer" << modm::endl;
SpiThread spiThread;

int main()
{
Board::initialize();

MODM_LOG_INFO << "Hello from SPI-DMA example on Nucleo-F429ZI!" << modm::endl;

uint32_t counter{0};

while (true)
{
if(++counter == 100000) {
MODM_LOG_INFO << ".";
counter = 0;
}
spiThread.update();
uint32_t cr = DMA2_Stream0->CR;
uint32_t par = DMA2_Stream0->PAR;
uint32_t m0ar = DMA2_Stream0->M0AR;
uint32_t ndtr = DMA2_Stream0->NDTR;
if(cr)
MODM_LOG_INFO << "\t CR=" << modm::hex << cr << modm::endl;
if(par)
MODM_LOG_INFO << "\t PAR=" << modm::hex << par << modm::endl;
if(m0ar)
MODM_LOG_INFO << "\t M0AR=" << modm::hex << m0ar << modm::endl;
if(ndtr)
MODM_LOG_INFO << "\t NDTR=" << modm::hex << ndtr << modm::endl;
}

return 0;
Expand Down
2 changes: 2 additions & 0 deletions examples/nucleo_f429zi/spi_dma/project.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
<module>modm:platform:gpio</module>
<module>modm:platform:dma</module>
<module>modm:platform:spi:1</module>
<module>modm:processing:protothread</module>
<module>modm:processing:timer</module>
<module>modm:build:scons</module>
</modules>
</library>
27 changes: 9 additions & 18 deletions src/modm/platform/dma/stm32/dma.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,10 @@ public:
static void
start()
{
%% if dmaType in ["stm32-channel-request", "stm32-channel", "stm32-mux"]
ControlHal::clearInterruptFlags(uint32_t(Interrupt::Global) << (uint32_t(ChannelID) * 4));
ControlHal::clearInterruptFlags(InterruptFlags::All, ChannelID);
ChannelHal::start();
%% elif dmaType in ["stm32-stream-channel"]
ControlHal::clearInterruptFlags(Interrupt::All, ChannelID);
%% endif
}

/**
* Stop a DMA channel transfer
*/
Expand Down Expand Up @@ -295,20 +292,18 @@ public:
{
%% if dmaType in ["stm32-channel-request", "stm32-channel", "stm32-mux"]
static const uint32_t TC_Flag {
uint32_t(Interrupt::TransferComplete) << (uint32_t(ChannelID) * 4)
uint32_t(InterruptFlags::TransferComplete) << (uint32_t(ChannelID) * 4)
};
static const uint32_t TE_Flag {
uint32_t(Interrupt::Error) << (uint32_t(ChannelID) * 4)
uint32_t(InterruptFlags::Error) << (uint32_t(ChannelID) * 4)
};
%% elif dmaType in ["stm32-stream-channel"]
constexpr uint8_t offsetLut[8] = {0, 6, 16, 22, 0+32, 6+32, 16+32, 22+32};


static const uint64_t TC_Flag {
uint64_t(Interrupt::TransferComplete) << offsetLut[uint32_t(ChannelID)]
uint64_t(InterruptFlags::TransferComplete) << offsetLut[uint32_t(ChannelID)]
};
static const uint64_t TE_Flag {
uint64_t(Interrupt::Error) << offsetLut[uint32_t(ChannelID)]
uint64_t(InterruptFlags::Error) << offsetLut[uint32_t(ChannelID)]
};
%% endif

Expand All @@ -321,11 +316,7 @@ public:
if ((isr & TC_Flag) and transferComplete)
transferComplete();

%% if dmaType in ["stm32-channel-request", "stm32-channel"]
ControlHal::clearInterruptFlags(uint32_t(Interrupt::Global) << (uint32_t(ChannelID) * 4));
%% elif dmaType in ["stm32-stream-channel"]
ControlHal::clearInterruptFlags(Interrupt::All, ChannelID);
%% endif
ControlHal::clearInterruptFlags(InterruptFlags::Global, ChannelID);
}

/**
Expand All @@ -352,15 +343,15 @@ public:
* Enable the specified interrupt of the channel
*/
static void
enableInterrupt(Interrupt_t irq)
enableInterrupt(InterruptEnable_t irq)
{
ChannelHal::enableInterrupt(irq);
}
/**
* Disable the specified interrupt of the channel
*/
static void
disableInterrupt(Interrupt_t irq)
disableInterrupt(InterruptEnable_t irq)
{
ChannelHal::disableInterrupt(irq);
}
Expand Down
37 changes: 27 additions & 10 deletions src/modm/platform/dma/stm32/dma_base.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public:
%% endfor
};

%% elif dmaType in ["stm32-channel-request", "stm32-channel", "stm32-mux", "stm32-stream-channel"]
%% elif dmaType in ["stm32-channel-request", "stm32-channel", "stm32-mux"]
enum class
Channel
{
Expand Down Expand Up @@ -221,24 +221,41 @@ public:
};

%% if dmaType in ["stm32-stream-channel"]
enum class Interrupt {
enum class InterruptEnable {
DirectModeError = DMA_SxCR_DMEIE,
TransferError = DMA_SxCR_TEIE,
HalfTransfer = DMA_SxCR_HTIE,
TransferComplete = DMA_SxCR_TCIE,
};
MODM_FLAGS32(InterruptEnable);

enum class InterruptFlags {
FifoError = 0b00'0001,
DirectModeError = 0b00'0100,
Error = 0b00'1000,
HalfTransferComplete = 0b01'0000,
TransferComplete = 0b10'0000,
All = 0b11'1101,
Global = All,
};
%% elif dmaType in ["stm32-channel-request", "stm32-channel"]
enum class Interrupt {
Global = 0x01,
TransferComplete = 0x02,
HalfTransferComplete = 0x04,
Error = 0x08,
All = 0x0f,
MODM_FLAGS32(InterruptFlags);
%% elif dmaType in ["stm32-channel-request", "stm32-channel", "stm32-mux"]
enum class InterruptEnable {
TransferComplete = DMA_CCR_TCIE,
HalfTransfer = DMA_CCR_HTIE,
TransferError = DMA_CCR_TEIE,
};
MODM_FLAGS32(InterruptEnable);

enum class InterruptFlags {
Global = 0b0001,
TransferComplete = 0b0010,
HalfTransferComplete = 0b0100,
Error = 0b1000,
All = 0b1111,
};
MODM_FLAGS32(InterruptFlags);
%% endif
MODM_FLAGS32(Interrupt);

using IrqHandler = void (*)(void);

Expand Down
17 changes: 6 additions & 11 deletions src/modm/platform/dma/stm32/dma_hal.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -117,18 +117,13 @@ public:
static constexpr uint32_t CHANNEL_2_CHANNEL { 0x18 };
%% endif

%% if dmaType in ["stm32-channel-request", "stm32-channel", "stm32-mux"]
static void
clearInterruptFlags(uint32_t flags)
clearInterruptFlags(InterruptFlags flags, DmaBase::Channel ChannelID)
{
DMA_TypeDef *DMA = reinterpret_cast<DMA_TypeDef *>(DMA_BASE);
DMA->IFCR = flags;
}
%% if dmaType in ["stm32-channel-request", "stm32-channel", "stm32-mux"]
DMA->IFCR = uint32_t(flags) << (uint32_t(ChannelID) * 4);
%% elif dmaType in ["stm32-stream-channel"]
static void
clearInterruptFlags(Interrupt flags, DmaBase::Channel ChannelID)
{
DMA_TypeDef *DMA = reinterpret_cast<DMA_TypeDef *>(DMA_BASE);
uint8_t ch = uint8_t(ChannelID);
constexpr uint8_t offsetLut[4] = {0, 6, 16, 22};
if(ch < 4) {
Expand All @@ -137,8 +132,8 @@ public:
else if(ch < 8) {
DMA->HIFCR = uint32_t(flags) << offsetLut[ch-4];
}
}
%% endif
}

%% if dmaType in ["stm32-channel-request", "stm32-channel", "stm32-mux"]
static uint32_t
Expand Down Expand Up @@ -311,7 +306,7 @@ public:
* Enable IRQ of this DMA channel (e.g. transfer complete or error)
*/
static void
enableInterrupt(Interrupt_t irq)
enableInterrupt(InterruptEnable_t irq)
{
DMA_Channel_TypeDef *Base = (DMA_Channel_TypeDef *) CHANNEL_BASE;
Base->{{ cr }} |= irq.value;
Expand All @@ -320,7 +315,7 @@ public:
* Disable IRQ of this DMA channel (e.g. transfer complete or error)
*/
static void
disableInterrupt(Interrupt_t irq)
disableInterrupt(InterruptEnable_t irq)
{
DMA_Channel_TypeDef *Base = (DMA_Channel_TypeDef *) CHANNEL_BASE;
Base->{{ cr }} &= ~(irq.value);
Expand Down
8 changes: 4 additions & 4 deletions src/modm/platform/spi/stm32/spi_master_dma_impl.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ modm::platform::SpiMaster{{ id }}_Dma<DmaChannelRx, DmaChannelTx>::initialize()
Dma::RxChannel::setTransferErrorIrqHandler(handleDmaTransferError);
Dma::RxChannel::setTransferCompleteIrqHandler(handleDmaReceiveComplete);
Dma::RxChannel::enableInterruptVector();
Dma::RxChannel::enableInterrupt(DmaBase::Interrupt::Error |
DmaBase::Interrupt::TransferComplete);
Dma::RxChannel::enableInterrupt(DmaBase::InterruptEnable::TransferError |
DmaBase::InterruptEnable::TransferComplete);
Dma::RxChannel::template setPeripheralRequest<Dma::RxRequest>();

Dma::TxChannel::configure(DmaBase::DataTransferDirection::MemoryToPeripheral,
Expand All @@ -39,8 +39,8 @@ modm::platform::SpiMaster{{ id }}_Dma<DmaChannelRx, DmaChannelTx>::initialize()
Dma::TxChannel::setTransferErrorIrqHandler(handleDmaTransferError);
Dma::TxChannel::setTransferCompleteIrqHandler(handleDmaTransmitComplete);
Dma::TxChannel::enableInterruptVector();
Dma::TxChannel::enableInterrupt(DmaBase::Interrupt::Error |
DmaBase::Interrupt::TransferComplete);
Dma::TxChannel::enableInterrupt(DmaBase::InterruptEnable::TransferError |
DmaBase::InterruptEnable::TransferComplete);
Dma::TxChannel::template setPeripheralRequest<Dma::TxRequest>();

SpiMaster{{ id }}::initialize<SystemClock, baudrate, tolerance>();
Expand Down

0 comments on commit e8f2aa4

Please sign in to comment.