stm32f0: systick_blink: Robustness and correctness fixes

Update documentation and comments in code to reflect reality.
Ensure that GPIO pin output speed is actually set, to ensure that 48Mhz sysclk
output is functional.
Actually set AF, instead of relying on reset values.
Replace the systick code, the core of this example, with some code that has
less traps and surprises.  Instead of trying to get a direct interrupt x times
per second, and reguarly running into problems with the 24 bit counter limit,
use a method that triggers an interrupt every x ms instead.  Tested MCO and
blink rates with a logic analyser, properly verified working now :)
This commit is contained in:
Karl Palsson
2016-04-07 22:04:03 +00:00
parent dfc4763ab3
commit b50cdb56de
2 changed files with 21 additions and 16 deletions

View File

@@ -10,4 +10,4 @@ to debug the PLL clock setup by scope.
| Port | Function | Description | | Port | Function | Description |
| ----- | -------- | ------------------------ | | ----- | -------- | ------------------------ |
| `PA9` | `(MCO)` | Internal reference clock | | `PA8` | `(MCO)` | Internal reference clock |

View File

@@ -30,14 +30,19 @@ void sys_tick_handler(void)
gpio_toggle(GPIOC, GPIO8); gpio_toggle(GPIOC, GPIO8);
} }
/* Set up timer to fire freq times per second */ /*
static void systick_setup(int freq) * Set up timer to fire every x milliseconds
* This is a unusual usage of systick, be very careful with the 24bit range
* of the systick counter! You can range from 1 to 2796ms with this.
*/
static void systick_setup(int xms)
{ {
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB); /* div8 per ST, stays compatible with M3/M4 parts, well done ST */
systick_set_clocksource(STK_CSR_CLKSOURCE_EXT);
/* clear counter so it starts right away */ /* clear counter so it starts right away */
STK_CVR = 0; STK_CVR = 0;
systick_set_reload(rcc_ahb_frequency / freq); systick_set_reload(rcc_ahb_frequency / 8 / 1000 * xms);
systick_counter_enable(); systick_counter_enable();
systick_interrupt_enable(); systick_interrupt_enable();
} }
@@ -49,23 +54,23 @@ static void clock_setup(void)
/* Enable clocks to the GPIO subsystems */ /* Enable clocks to the GPIO subsystems */
rcc_periph_clock_enable(RCC_GPIOC); rcc_periph_clock_enable(RCC_GPIOC);
rcc_periph_clock_enable(RCC_GPIOA);
} }
static void gpio_setup(void) static void gpio_setup(void)
{ {
/* Select pin functions. PC8/PC9 are the two LEDs on the /* Set blue led (PC8) as output */
STM32F0DISCOVERY board. */ gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO8);
gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO8 | GPIO9);
/* set GPIOA to AF 0 */
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO8);
} }
static void mco_setup(void) static void mco_setup(void)
{ {
/* Enable system clock output on pin PA8 (so it can be checked with a /* PA8 to AF 0 for MCO */
scope) */ rcc_periph_clock_enable(RCC_GPIOA);
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO8);
gpio_set_output_options(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO8);
gpio_set_af(GPIOA, 0, GPIO8);
/* clock output on pin PA8 (allows checking with scope) */
rcc_set_mco(RCC_CFGR_MCO_SYSCLK); rcc_set_mco(RCC_CFGR_MCO_SYSCLK);
} }
@@ -75,8 +80,8 @@ int main(void)
gpio_setup(); gpio_setup();
mco_setup(); mco_setup();
/* setup systick to generate 2 LED flashes per second */ /* 125ms ticks => 250ms period => 4Hz blinks */
systick_setup(8); systick_setup(125);
/* Do nothing in main loop */ /* Do nothing in main loop */
while (1); while (1);