stm32_common: add delay when turn on peripheral clock

Implements workaround 1 (use __DSB()) proposed in the stm32 errata
It was possible to lose data when you configure a peripheral
right after enabling its clock
pr/spi.typo
Pieter Willemsen 7 years ago
parent 79043d2518
commit 2b37d369a0

@ -21,6 +21,9 @@
#include "periph_conf.h"
#include "periph_cpu_common.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
uint32_t periph_apb_clk(uint8_t bus)
{
if (bus == APB1) {
@ -31,20 +34,66 @@ uint32_t periph_apb_clk(uint8_t bus)
}
}
void periph_clk_en(uint8_t bus, uint32_t mask)
void periph_clk_en(bus_t bus, uint32_t mask)
{
if (bus == APB1) {
RCC->APB1ENR |= mask;
} else {
RCC->APB2ENR |= mask;
switch (bus) {
case APB1:
RCC->APB1ENR |= mask;
break;
case APB2:
RCC->APB2ENR |= mask;
break;
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1) || defined(CPU_FAM_STM32F1) \
|| defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3)
case AHB:
RCC->AHBENR |= mask;
break;
#elif defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4)
case AHB1:
RCC->AHB1ENR |= mask;
break;
case AHB2:
RCC->AHB2ENR |= mask;
break;
case AHB3:
RCC->AHB3ENR |= mask;
break;
#endif
default:
DEBUG("unsupported bus %d\n", (int)bus);
break;
}
/* stm32xx-errata: Delay after a RCC peripheral clock enable */
__DSB();
}
void periph_clk_dis(uint8_t bus, uint32_t mask)
void periph_clk_dis(bus_t bus, uint32_t mask)
{
if (bus == APB1) {
RCC->APB1ENR &= ~(mask);
} else {
RCC->APB2ENR &= ~(mask);
switch (bus) {
case APB1:
RCC->APB1ENR &= ~(mask);
break;
case APB2:
RCC->APB2ENR &= ~(mask);
break;
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1) || defined(CPU_FAM_STM32F1) \
|| defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3)
case AHB:
RCC->AHBENR &= ~(mask);
break;
#elif defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4)
case AHB1:
RCC->AHB1ENR &= ~(mask);
break;
case AHB2:
RCC->AHB2ENR &= ~(mask);
break;
case AHB3:
RCC->AHB3ENR &= ~(mask);
break;
#endif
default:
DEBUG("unsupported bus %d\n", (int)bus);
break;
}
}

@ -47,10 +47,20 @@ extern "C" {
/**
* @brief Available peripheral buses
*/
enum {
typedef enum {
APB1, /**< APB1 bus */
APB2 /**< APB2 bus */
};
APB2, /**< APB2 bus */
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1) || defined(CPU_FAM_STM32F1)\
|| defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3)
AHB, /**< AHB bus */
#elif defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4)
AHB1, /**< AHB1 bus */
AHB2, /**< AHB2 bus */
AHB3 /**< AHB3 bus */
#else
#warning "unsupported stm32XX family"
#endif
} bus_t;
/**
* @brief Overwrite the default gpio_t type definition
@ -132,7 +142,7 @@ uint32_t periph_apb_clk(uint8_t bus);
* @param[in] bus bus the peripheral is connected to
* @param[in] mask bit in the RCC enable register
*/
void periph_clk_en(uint8_t bus, uint32_t mask);
void periph_clk_en(bus_t bus, uint32_t mask);
/**
* @brief Disable the given peripheral clock
@ -140,7 +150,7 @@ void periph_clk_en(uint8_t bus, uint32_t mask);
* @param[in] bus bus the peripheral is connected to
* @param[in] mask bit in the RCC enable register
*/
void periph_clk_dis(uint8_t bus, uint32_t mask);
void periph_clk_dis(bus_t bus, uint32_t mask);
/**
* @brief Configure the given pin to be used as ADC input

@ -48,15 +48,13 @@ int8_t dac_init(dac_t line)
gpio_init_analog(dac_config[line].pin);
/* enable the DAC's clock */
#if defined(DAC2)
RCC->APB1ENR |= dac_config[line].dac
? RCC_APB1ENR_DAC2EN
: RCC_APB1ENR_DAC1EN;
periph_clk_en(APB1, dac_config[line].dac ?
RCC_APB1ENR_DAC2EN : RCC_APB1ENR_DAC1EN);
#elif defined(DAC1)
RCC->APB1ENR |= RCC_APB1ENR_DAC1EN;
periph_clk_en(APB1, RCC_APB1ENR_DAC1EN);
#else
RCC->APB1ENR |= RCC_APB1ENR_DACEN;
periph_clk_en(APB1, RCC_APB1ENR_DACEN);
#endif
/* reset output and enable the line's channel */
dac_set(line, 0);
dac_poweron(line);

Loading…
Cancel
Save