stm32/dma: Add support for DMA on STM32WB, with SPI settings provided.

This commit is contained in:
Damien George 2020-06-01 21:32:03 +10:00
parent 0f7b5cceea
commit c8985d52d3
1 changed files with 53 additions and 22 deletions

View File

@ -34,18 +34,6 @@
#include "dma.h" #include "dma.h"
#include "irq.h" #include "irq.h"
#if defined(STM32WB)
// DMA is currently not implemented for this MCU
void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir, void *data) {
}
void dma_deinit(const dma_descr_t *dma_descr) {
}
#else
#define DMA_IDLE_ENABLED() (dma_idle.enabled != 0) #define DMA_IDLE_ENABLED() (dma_idle.enabled != 0)
#define DMA_SYSTICK_LOG2 (3) #define DMA_SYSTICK_LOG2 (3)
#define DMA_SYSTICK_MASK ((1 << DMA_SYSTICK_LOG2) - 1) #define DMA_SYSTICK_MASK ((1 << DMA_SYSTICK_LOG2) - 1)
@ -82,7 +70,7 @@ typedef union {
struct _dma_descr_t { struct _dma_descr_t {
#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7)
DMA_Stream_TypeDef *instance; DMA_Stream_TypeDef *instance;
#elif defined(STM32F0) || defined(STM32L0) || defined(STM32L4) #elif defined(STM32F0) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB)
DMA_Channel_TypeDef *instance; DMA_Channel_TypeDef *instance;
#else #else
#error "Unsupported Processor" #error "Unsupported Processor"
@ -97,7 +85,7 @@ struct _dma_descr_t {
static const DMA_InitTypeDef dma_init_struct_spi_i2c = { static const DMA_InitTypeDef dma_init_struct_spi_i2c = {
#if defined(STM32F4) || defined(STM32F7) #if defined(STM32F4) || defined(STM32F7)
.Channel = 0, .Channel = 0,
#elif defined(STM32H7) || defined(STM32L0) || defined(STM32L4) #elif defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB)
.Request = 0, .Request = 0,
#endif #endif
.Direction = 0, .Direction = 0,
@ -120,7 +108,7 @@ static const DMA_InitTypeDef dma_init_struct_spi_i2c = {
static const DMA_InitTypeDef dma_init_struct_sdio = { static const DMA_InitTypeDef dma_init_struct_sdio = {
#if defined(STM32F4) || defined(STM32F7) #if defined(STM32F4) || defined(STM32F7)
.Channel = 0, .Channel = 0,
#elif defined(STM32L0) || defined(STM32L4) #elif defined(STM32L0) || defined(STM32L4) || defined(STM32WB)
.Request = 0, .Request = 0,
#endif #endif
.Direction = 0, .Direction = 0,
@ -130,7 +118,7 @@ static const DMA_InitTypeDef dma_init_struct_sdio = {
.MemDataAlignment = DMA_MDATAALIGN_WORD, .MemDataAlignment = DMA_MDATAALIGN_WORD,
#if defined(STM32F4) || defined(STM32F7) #if defined(STM32F4) || defined(STM32F7)
.Mode = DMA_PFCTRL, .Mode = DMA_PFCTRL,
#elif defined(STM32L0) || defined(STM32L4) #elif defined(STM32L0) || defined(STM32L4) || defined(STM32WB)
.Mode = DMA_NORMAL, .Mode = DMA_NORMAL,
#endif #endif
.Priority = DMA_PRIORITY_VERY_HIGH, .Priority = DMA_PRIORITY_VERY_HIGH,
@ -148,7 +136,7 @@ static const DMA_InitTypeDef dma_init_struct_sdio = {
static const DMA_InitTypeDef dma_init_struct_dac = { static const DMA_InitTypeDef dma_init_struct_dac = {
#if defined(STM32F4) || defined(STM32F7) #if defined(STM32F4) || defined(STM32F7)
.Channel = 0, .Channel = 0,
#elif defined(STM32H7) || defined(STM32L0) || defined(STM32L4) #elif defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB)
.Request = 0, .Request = 0,
#endif #endif
.Direction = 0, .Direction = 0,
@ -438,6 +426,40 @@ static const uint8_t dma_irqn[NSTREAM] = {
DMA2_Channel7_IRQn, DMA2_Channel7_IRQn,
}; };
#elif defined(STM32WB)
#define NCONTROLLERS (2)
#define NSTREAMS_PER_CONTROLLER (7)
#define NSTREAM (NCONTROLLERS * NSTREAMS_PER_CONTROLLER)
#define DMA_SUB_INSTANCE_AS_UINT8(dma_request) (dma_request)
#define DMA1_ENABLE_MASK (0x007f) // Bits in dma_enable_mask corresponding to DMA1
#define DMA2_ENABLE_MASK (0x3f80) // Bits in dma_enable_mask corresponding to DMA2
// DMA1 streams
const dma_descr_t dma_SPI_1_RX = { DMA1_Channel1, DMA_REQUEST_SPI1_RX, dma_id_0, &dma_init_struct_spi_i2c };
const dma_descr_t dma_SPI_1_TX = { DMA1_Channel2, DMA_REQUEST_SPI1_TX, dma_id_1, &dma_init_struct_spi_i2c };
const dma_descr_t dma_SPI_2_RX = { DMA1_Channel3, DMA_REQUEST_SPI2_RX, dma_id_2, &dma_init_struct_spi_i2c };
const dma_descr_t dma_SPI_2_TX = { DMA1_Channel4, DMA_REQUEST_SPI2_TX, dma_id_3, &dma_init_struct_spi_i2c };
static const uint8_t dma_irqn[NSTREAM] = {
DMA1_Channel1_IRQn,
DMA1_Channel2_IRQn,
DMA1_Channel3_IRQn,
DMA1_Channel4_IRQn,
DMA1_Channel5_IRQn,
DMA1_Channel6_IRQn,
DMA1_Channel7_IRQn,
DMA2_Channel1_IRQn,
DMA2_Channel2_IRQn,
DMA2_Channel3_IRQn,
DMA2_Channel4_IRQn,
DMA2_Channel5_IRQn,
DMA2_Channel6_IRQn,
DMA2_Channel7_IRQn,
};
#elif defined(STM32H7) #elif defined(STM32H7)
#define NCONTROLLERS (2) #define NCONTROLLERS (2)
@ -717,7 +739,7 @@ void DMA1_Channel4_5_6_7_IRQHandler(void) {
IRQ_EXIT(DMA1_Channel4_5_6_7_IRQn); IRQ_EXIT(DMA1_Channel4_5_6_7_IRQn);
} }
#elif defined(STM32L4) #elif defined(STM32L4) || defined(STM32WB)
void DMA1_Channel1_IRQHandler(void) { void DMA1_Channel1_IRQHandler(void) {
IRQ_ENTER(DMA1_Channel1_IRQn); IRQ_ENTER(DMA1_Channel1_IRQn);
@ -836,6 +858,13 @@ static void dma_enable_clock(dma_id_t dma_id) {
dma_enable_mask |= (1 << dma_id); dma_enable_mask |= (1 << dma_id);
MICROPY_END_ATOMIC_SECTION(irq_state); MICROPY_END_ATOMIC_SECTION(irq_state);
#if defined(STM32WB)
// This MCU has a DMAMUX peripheral which needs to be enabled to multiplex the channels.
if (!__HAL_RCC_DMAMUX1_IS_CLK_ENABLED()) {
__HAL_RCC_DMAMUX1_CLK_ENABLE();
}
#endif
if (dma_id < NSTREAMS_PER_CONTROLLER) { if (dma_id < NSTREAMS_PER_CONTROLLER) {
if (((old_enable_mask & DMA1_ENABLE_MASK) == 0) && !DMA1_IS_CLK_ENABLED()) { if (((old_enable_mask & DMA1_ENABLE_MASK) == 0) && !DMA1_IS_CLK_ENABLED()) {
__HAL_RCC_DMA1_CLK_ENABLE(); __HAL_RCC_DMA1_CLK_ENABLE();
@ -877,7 +906,7 @@ void dma_init_handle(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint3
dma->Instance = dma_descr->instance; dma->Instance = dma_descr->instance;
dma->Init = *dma_descr->init; dma->Init = *dma_descr->init;
dma->Init.Direction = dir; dma->Init.Direction = dir;
#if defined(STM32L0) || defined(STM32L4) || defined(STM32H7) #if defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB)
dma->Init.Request = dma_descr->sub_instance; dma->Init.Request = dma_descr->sub_instance;
#else #else
#if !defined(STM32F0) #if !defined(STM32F0)
@ -904,7 +933,7 @@ void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir
dma_enable_clock(dma_id); dma_enable_clock(dma_id);
#if defined(STM32H7) || defined(STM32L0) || defined(STM32L4) #if defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB)
// Always reset and configure the H7 and L0/L4 DMA peripheral // Always reset and configure the H7 and L0/L4 DMA peripheral
// (dma->State is set to HAL_DMA_STATE_RESET by memset above) // (dma->State is set to HAL_DMA_STATE_RESET by memset above)
// TODO: understand how L0/L4 DMA works so this is not needed // TODO: understand how L0/L4 DMA works so this is not needed
@ -1062,6 +1091,10 @@ void dma_nohal_start(const dma_descr_t *descr, uint32_t src_addr, uint32_t dst_a
dma->CCR |= DMA_CCR_EN; dma->CCR |= DMA_CCR_EN;
} }
#elif defined(STM32WB)
// These functions are currently not implemented or needed for this MCU.
#else #else
void dma_nohal_init(const dma_descr_t *descr, uint32_t config) { void dma_nohal_init(const dma_descr_t *descr, uint32_t config) {
@ -1135,5 +1168,3 @@ void dma_nohal_start(const dma_descr_t *descr, uint32_t src_addr, uint32_t dst_a
} }
#endif #endif
#endif // defined(STM32WB)