2019-12-04 10:16 PM
Oh there are so many more details... The short story is that I recently got a freelance job converting an old 6800 based controller box to use the STM32 boards. The basic idea is that we will have various things happening in the real world that need to trigger some action from the control software. The obvious solution is interrupts. I must confess that I find the STM32 documentation rather baffling and it is difficult to see exactly what I'm supposed to do in STM32CubeIDE to just connect an interrupt coming in on a pin to an interrupt handler. There's all kinds of stuff online about clocks but very few simple tutorials that show how to do this one simple thing. I've done this kind of work before using Arduinos and that world seems like the opposite extreme of simplicity. Can anyone point me to a good, well written set of tutorials on how to get basic things like interrupts and peripherals running? So far I've managed to make a simple "blink" app and can read the state of the blue button (just polling it, not using interrupts). I'm willing to abandon STM32CubeIDE if there's a better way to get this going but I need a way to use the integrated stepping ST-Link debugging while we test the code.
2019-12-04 11:22 PM
Let's start with that you change your username to a normal nick.
> Can anyone point me to a good, well written set of tutorials
No. There are simply none.
The vast majority of material available evolves around some ST "library" - the older ones around so called Standard Peripheral Library (SPL) (which is mostly a "wrapper", basically just renaming the peripheral registers) and the newer ones around Cube/HAL. Then there are third party ones, too, with even lesser tutorials and documentation but supposedly more mojo, like mbed and some form of arduino. These days you are mostly supposed to point and click (that's probably what you see in CubeIDE, or CubeMX) - which may be nice, if your job is a simple-minded one, arduino style, i.e. if you won't ever depart from the inevitably limited usage modes envisaged by the "libraries" authors.
So the landscape is pretty much fragmented and you have to hand-pick the wisdom yourself.
Your basic literature is mostly to be found in the webfolder for the given STM32 model (yes I know those folders are a mess) - the Datasheet (DS), the Reference Manual (RM), the Errata (ES) for your STM32 model. And then, for the foundations, ARM's material for the processor core, digested into so called Programming Manual, but you may want to reach out for Joseph Yiu's books, which are basically the ARM manuals (which you can get at ARM's site) but rewritten from ARM's signature mess into the form they were supposed to be at the first place.
I don't know how to use the CubeIDE for normal programming. I don't use it, I loathe the Eclipsoids.
The RM may be overwhelming, but at least skim over the few dozen or so chapters (before it gets deep into specific peripherals). The "registers" subchapters are often more enlightening than the narrative, which is written by non-english and often obviously unexperienced writers.
A good programming practice is to stick to the symbols for registers given in the NVIC-mandated device headers, to be found in [Cube for given STM32 family]\Drivers\CMSIS\Device\ST\[family]\Include\. Unfortunately, ST does not provide concise set symbols for values except the single-bit ones (mostly); they do it haphazardly in the individual "libraries", I started to write my own augmented headers for this.
The basic workflow is:
For interrupts, you
Examples of my approach here - this is not tutorial-grade stuff, though. Timer interrupt example in "bitband dangerous".
A useless example of EXTI usage below (it's been written for https://community.st.com/s/question/0D50X00009XkfHrSAJ/software-interrupt-on-stm32l4 but that lost its formatting courtesy of dilettantish forum migration)
HTH,
JW
// (C)2018 wek at efton dot sk
// simple extint example
// https://community.st.com/message/201572-re-software-interrupt-on-stm32l4
// 'L476 DISCO
// RED LED on DISCOL4 is PB2
// PA5 - JOY_DOWN
// pressing JOY_DOWN triggers EXTI1, which in ISR toggles the red LED
// default 4MHz MSI clock
#include <stdint.h>
#include "stm32l476xx.h"
#include "stm32l476xxx_augment.h"
#include "common.h"
// -------- trivial loopdelay
volatile uint32_t __attribute__((section(".ram2"))) delayN;
void LoopDelay(uint32_t n) {
delayN = n;
while(delayN > 0) delayN--;
}
#define DELAY_CONSTANT 50000
// ISR
void EXTI1_IRQHandler(void) __attribute__((interrupt));
void EXTI1_IRQHandler(void) {
uint32_t pr;
pr = EXTI->PR1 & (1 << 1);
EXTI->PR1 = pr; // clear pending interrupts by writing 1
if (pr & (1 << 1)) {
// toggle LED
if (GPIOB->ODR AND (1 << 2)) {
GPIOB->BSRR = (1 << 2) << 16;
} else {
GPIOB->BSRR = (1 << 2);
}
}
}
// -------- main
int main(void) {
RCC->AHB2ENR |= 0
| RCC_AHB2ENR_GPIOAEN
| RCC_AHB2ENR_GPIOBEN
;
GPIOA->PUPDR = (GPIOA->PUPDR
& (~GPIO_PUPDR_PUPD5)
) | (0
| (GPIO_PullDown * GPIO_PUPDR_PUPD5_0) // JOY surprisingly switches to +3V!
);
;
GPIOA->MODER = (GPIOA->MODER
& (~GPIO_MODER_MODER5)
) | (0
| (GPIO_Mode_In * GPIO_MODER_MODER5_0) // PA5 - JOY_DOWN - TIM2_CH1
);
GPIOB->MODER = (GPIOB->MODER
& (~GPIO_MODER_MODER2)
) | (0
| (GPIO_Mode_Out * GPIO_MODER_MODER2_0) // PB3 (jumper to PB2-RED LED)
);
NVIC_SetPriority(EXTI1_IRQn, 3); // Set priority
NVIC_EnableIRQ(EXTI1_IRQn);
EXTI->IMR1 = 1 << 1;
EXTI->EMR1 = 1 << 1; // this is not needed, but we add it to mimic the code in post
while(1) {
static _Bool down;
unsigned i;
#define DEBOUNCE_CNT 4000
if (down) {
if ((GPIOA->IDR & GPIO_IDR_ID5_Msk) == 0) down = 0;
} else {
for (i = 0; i < DEBOUNCE_CNT; i++) {
if ((GPIOA->IDR & GPIO_IDR_ID5_Msk) == 0) break;
}
if (i == DEBOUNCE_CNT) {
down = 1;
EXTI->SWIER1 = 1 << 1;
}
}
}
}
2019-12-05 08:37 AM
ST has online training on several MCU families. Unfortunately, F4 is not covered (yet?)
-- pa
2020-07-10 10:44 AM
Hello, I'm trying to find out if you ever got around to this: "a .s file, something like startup_stm32?????xx.s - we will get to this later again"
I'm trying to setup a minimal possibly barebones template in STM32CubeIDE for a Nucleo STM32H755ZI-Q. I'd like to ditch the .ico and write my own code at the HAL level or lower. The startup file (.s) documentation says that it does the following:
I was curious what you had to say about this file. I'm guessing I should keep it since I see it's present in your basic Blinky example. Are there any changes to it that you would recommend?
edit: Also, I don't see a void SystemClock_Config(void) type function in your examples. Is that not required for a minimal project? Looks like I have a lot to learn
2020-07-10 02:07 PM
'H7 is a complex beast, I'm not sure it's the best option to start. I don't use any Cortex-M7, much of work is on the control side.
I use startup file coming from the "libraries". SPL tended to call click so from there, I removed that. I also removed any C-library (newlib) related calls, that might perhaps backfire at me later, but I generally avoid <stdio.h> facilities in embedded environment. I do enable the FPU/coprocessor in the startup asm code where fpu is present and enabled for compiler, as the prologue to main () generated by compiler then may contain code using FPU registers.
I don't enable and clear external memories (nor the non-continuous portions of internal RAM) in the startup, I do it at the beginning of main (). Maybe that will backfire at me one day, too, but I do that knowingly.
In most of the examples there was no reason to use anything else than the default clock (HSI/MSI depending on STM32 model), there may be examples where HSE/PLL is used, but I then switch it using a few lines at the beginning of main(), I don't see any reason to write a separate function for such a simple task.
YMMV
JW