It’s nice to see the interest of the community about our job on porting the STM32 on Arduino.
We would like to introduce our job and to respond to your questions about our choices of implementation.
First of all, the goal of the delivery is to provide the same functionalities that you can have when you buy an arduino Uno and that you need to launch the sketches.
We tried to build something generic and not too much hard to customize.
We decided to divide the project in 2 parts:
-The lib that contains the access to the drivers and to the MCU configuration. The library contains the STM32 HAL. It is compiled independently.
ST requested to use the HAL as it is maintained by the ST teams so you can easily integrate new functionalities .
-The arduino core with the Wirish interface and the variant.
Their should not have any direct reference to the Hardware registers into the arduino core.
We clearly understand the questions about the memory footprint but this project is a compromise to make the STM32 HAL work the more efficiently with the arduino core, the simpliest way.
So if you have any questions, don’t hesitate and we will try to respond.
BR
Wi6Labs team
Thanks for posting, I think it will be very useful if we can ask questions about the software you wrote.
We have some questions about how to add more boards from the same MCU series e.g. STM32F1
The old “LibMaple” core supported the STM32F103Cx , STM32F103Rx. STM32F103Vx and STM32F103Zx series
@rickKimbal has started to add a “BluePill” board (STM32F103C8) to the F103 core, but we realised that there were differences in the hw_config and we had to move this file from libstm32f1 to the variant folder.
This is discussed in 2 threads
http://www.stm32duino.com/viewtopic.php?f=48&t=1407
and
http://www.stm32duino.com/viewtopic.php?f=48&t=1406
Also. One thing we need to add is USB CDCACM, I don’t think any of the Nucleo boards have a direct USB connection, but most F103 boards make use of the built in USB port and we have a bootloader we use to upload.
BTW
I think perhaps I should move this whole thread to this section http://www.stm32duino.com/viewforum.php?f=48 as its dedicated to your work
We decided to divide the project in 2 parts:
-The lib that contains the access to the drivers and to the MCU configuration. The library contains the STM32 HAL. It is compiled independently.
ST requested to use the HAL as it is maintained by the ST teams so you can easily integrate new functionalities

-The arduino core with the Wirish interface and the variant.
Their should not have any direct reference to the Hardware registers into the arduino core.
Wi6Labs team
Also. One thing we need to add is USB CDCACM, I don’t think any of the Nucleo boards have a direct USB connection, but most F103 boards make use of the built in USB port and we have a bootloader we use to upload.
Frederic posted a list of the board they intend to support, but it only looked like one board per MCU series.
I will email Laurent, who is team leader for this at STM, as Frederic may now be away on paternity leave.
I think we will need to wait until tomorrow for a response from Wi6Labs, because its getting on for midnight in France
Btw. One other thing I noticed is that the pin names seem to be set using #defines, rather than enum.
If Wi6 are not doing any more work on the F1 core, I agree that more radical changes will be needed.
ST developed the NUCLEO board support for:
- STM32F103RBT6 STM32F303RET6 STM32F429ZIT6 STM32L476RG STM32F091RCT6 STM32L053R8T6
As you know these boards are hardware compatible with Arduino architecture. Now they are also software compatible.
As we said in previous post our goal is to provide generic interfaces to link the Arduino world with the STM32Cube world.
We understand there are multiple ways to implement such kind of “glue”. But we decided to make something very easy to use with the Arduino IDE.
We have some questions about how to add more boards from the same MCU series e.g. STM32F1
The old “LibMaple” core supported the STM32F103Cx , STM32F103Rx. STM32F103Vx and STM32F103Zx series
If you want to support other STM32 series we advice you to modify the library (libstm32f1). You can generate an archive with the makefile in build_gcc (some modifications are required). If you need more information on how to generate archive, we can help you.
Please also check the system/Drivers/CMSIS/Device/ST/STM32F1xx/Include for the list of supported boards.
Rick,
@Wi6Labs Do you plan on doing any more changes to the STM32F1 core?
Only if there is bug in the Arduino IDE for the STM32F103RB.
BR
Wi6Labs team
is possible can you read this thread
viewtopic.php?f=48&t=1407&start=40
There are already some questions about how we can add support for F103Vx and F103Zx series boards.
It looks like the code in libstm32f1 does not handle GPIO Ports, D E F or G, so we will need to update multpile files e.f. digital_io.c to add support for these GPIO ports ( the same probably applies to MCUs with more USARTS and also some F103 MCUs have UART as well as USARTS.
To create create a new variant, it looks like we may need to make a complete copy of libstm32 F1 ( in the system folder), but this is not ideal, as it will lead to a duplication of a lot of functions, which will be identical in many different boards.
So it alos looks like we woll need to split the global initialisation structures from inside files like digital_io.c and perhaps make a new file e.g digital_io_config.h which contains the global definitions structure.
I realise Wi6Labs will not be making any additional variants, but it would be very helpful if you could answer questions related to the code design etc, and perhaps suggest methods so we can support multiple additional MCUs in each series.
Thanks
Roger
It is easy to check if a specific port is defined, as HALMX defines the peripheral bases if the peripheral exists. As I can see, some ifdef’s are needed if we have to keep the same source files for GPIO, UARTS, etc at least for the checking of a peripheral existence. I know that you dont like ifdef’s but the other way to have multiple versions of library is the worst thing we could make.
In the STM32F1 core, can you explain how the stack is used? If I look at the linker file:
https://github.com/stm32duino/Arduino_C … ASH.ld#L49
The variable _estack is set to an address in the middle of RAM.
_estack = 0x20001FFF;
In addition, it is an odd address instead of even.
Why isn’t this variable set to the actually top of RAM (0x20005000) ?
-rick
It is a mistake. __estack must be set to 0x20005000, the last address of the SRAM.
We will report it to ST who will push the patch soon.
Thanks Rick.
Wi6Labs team
What would be the best way of adding a new variant that has different pin assignments than the variants you are supplying?
[Note:] I did read your previous answer and was looking for verification that that is indeed your solution.You seem to say that for each board we need to create a new library? Pins seem to have their attributes described in both the variant directory and the library directory. You can’t just redefine an analog pin with PWM to use another pin in the variant.cpp file, it has to also match the information in the analog.c in the library directory.
[/Note]
-rick
To answer to your questions how to add a new board:
Firstly, the project is base on Nucleo boards, so there is some feature not implemented in the core code (under system/libstm32f1).
So, you need to add some code in sources (as you have already done). You should create a new folder in variant for each board added. And you should generate the library for the new board (there is a makefile in system/libstm32f1/build_gcc). This makefile must be completed with the options of the new board.
Finally, to use the board with Arduino, you should complete the board.txt with the parameters of the new board.
You seem to say that for each board we need to create a new library? Pins seem to have their attributes described in both the variant directory and the library directory. You can’t just redefine an analog pin with PWM to use another pin in the variant.cpp file, it has to also match the information in the analog.c in the library directory.
You are limited in pin functions. So we need to define also in analog.c the pin configuration. In variant.cpp you just signal to Arduino how the pin can be used.
BR
Wi6Labs team
So, for instance, if I have two boards with the same chip (let’s say: STM32F407VET6), do I really have to make a new folder for each board variant?
Wouldn’t be more effective to separate the chip variants, and not the board variants?
I mean, when I am using the GPIOs, I always use the “PAx” style, so that even if the board is different, I get the same functionality for the same pin when the same chip is used.
Or am I missing something?
In the Arduino spirit you have one folder by board.
In your case, we understand that the hardware of your boards (that use the same chip) is different.
So we advice you to create 2 folders in variant.
Maybe it is not the best way in your case but we are opened for other solution from the community.
Wi6Labs team.
What if I wanted to add all the pins on the Nucleo boards and use the Morpho header with the Arduino core. What would be the best way to accomplish that?
I guess what I’m getting at, in a a round about way, is that the way the library and variants work together isn’t optimal. The library has pin knowledge. I contend that any pin knowledge should only be known by the variant. I’m suggesting that the library should be just that, a set of routines that can be used with any variant and any set of pin descriptions for the same chip. Any thoughts on that?
-rick
+++ Ollie
I had a couple of emails from STM and Wi6Labs, and basically it appears that Wi6 were only requested to create a system to handle Nucleo boards and hence had not designed a very flexibly architecture.
They sent me the handover document (which they said is confidential), but it doesn’t contain anything that we don’t already know, as its intended audience appears to be anyone that doesn’t know about the Arduino IDE and the structure of the third party cores.
I’d really like to get the first pass BluePill code into the repo this weekend, so I suppose I could just action Rick’s PR, but I’m still inclined to take a complete copy of libstm32 and make libstm32f103cx so that BluePill can be a variant of this, as could Maple mini
… but I’m still inclined to take a complete copy of libstm32 and make libstm32f103cx so that BluePill can be a variant of this, as could Maple mini
ST developed the NUCLEO board support for:
- STM32F103RBT6 STM32F303RET6 STM32F429ZIT6 STM32L476RG STM32F091RCT6 STM32L053R8T6
Wi6Labs team
The only source code released by STM, so far, has been for the Nucleo F103RB and the Nucleo L4 boards
My understanding is that they will release the source code for the other boards they listed, but that’s all they are going to do.
There are no plans to create “boards” (variants) for the Discovery series boards, let alone any generic boards or the Maple mini etc.
Unfortunately, it seems that the structure of the STM Core has not been designed with supporting mutliple boards using variants of the same MCU.
So we are going to have to work out how to do this ourselves, and probably re-factor the code.
But of course we need to try to not break the operation of the Nucleo boards which STM have already tested and verified is working.
Hence I’m in the process of making complete copies of the folder that is used to generate the Nucleo F103RB, so that we can make radical modifications to it if necessary.
Note. Actually, we’ll need to change the Nucleo F103RB code as well, as Rick has already found an error in the linker file.
But I expect we will keep changes to a minimum so that they are only bug fixes.
I see the Nucleo STM32L476RG is one of the supported boards. Has anyone on here got one working with the new core?
What is the situation with libraries. If I wanted to use, say, existing Arduino wire, MIDI and I2C LCD libraries, are they likely to work without too much hassle?
Sorry if these are basic questions. I was about to start a new project based on a Mega 2560 board but am concerned about whether I will have enough program space so am reviewing my options. My current STM32 experience is limited to loading blink programs on F103 boards.
( but I could be mistaken)
STM said they would send me a few boards to test with, but they seem to have got lost in the post
Re:Libraries
I dont think anyone has tested them yet, but the Core comes with the standard libs like Wire and SPI.
But no USB support at all.
I’m currently working on adding USB serial, but to get all the USB devices working well, actually requires quite a major overhaul of the STMCubeMx generated code, as we need a Composite USB device and I dont think the Cube has an option to generate example code like that.
I am sure we could get individual USB devices, like MIDI and HID working one at a time, but this is far from ideal
The L476 is an exceptional MCU (my favorite STM32 MCU) and you can test also the core of GrumpyOldPizza from http://www.stm32duino.com/viewtopic.php?f=42&t=1092
It is for a custom L476 board (dragonfly), it is very well written, on top of CMSIS (optimized), with complete core functions (and more than that), definitely a very good piece of code.
More for DragonFly (photos, schematics, pcb) here: https://www.tindie.com/products/onehors … ent-board/
What are the features and functionality in Dragonfly STM32L4 that you like in comparison to Teensy 3.2/3.5/3.6? They are in same price range, but Teensy has more I/O, higher performance, and excellent S/W libraries.
Cheers, Ollie
What are the features and functionality in Dragonfly STM32L4 that you like in comparison to Teensy 3.2/3.5/3.6? They are in same price range, but Teensy has more I/O, higher performance, and excellent S/W libraries.
Cheers, Ollie
The Dragonfly board looks interesting, but the price for a board delivered to the UK is 45 UK pounds (with probable additional customs charges on top) —- a bit over my budget for this project. I can get a Nucleo STM32L476RG board for 11 UK pounds from Farnell, so that’s a better option for me if I can get it to output MIDI and support a 1602 LCD or other small display device.
Edit: Just to clarify, I don’t need MIDI over USB —- I just plan to wire the TX pin to a 5-pin MIDI jack.
What are the features and functionality in Dragonfly STM32L4 that you like in comparison to Teensy 3.2/3.5/3.6? They are in same price range, but Teensy has more I/O, higher performance, and excellent S/W libraries.
Cheers, Ollie
The Dragonfly board looks interesting, but the price for a board delivered to the UK is 45 UK pounds (with probable additional customs charges on top) —- a bit over my budget for this project. I can get a Nucleo STM32L476RG board for 11 UK pounds from Farnell, so that’s a better option for me if I can get it to output MIDI and support a 1602 LCD or other small display device.
Edit: Just to clarify, I don’t need MIDI over USB —- I just plan to wire the TX pin to a 5-pin MIDI jack.
Sorry about the pricing. Perhaps we’ll do a cheaper board with a L433 or such. Please keep in mind that STM’s Nucleo boards are sold below cost. It’s kind of hard to compete against that.
What is the situation with libraries. If I wanted to use, say, existing Arduino wire, MIDI and I2C LCD libraries, are they likely to work without too much hassle?
…
Will there be a define that can be used to ifdef in the libraries, like there are already ifdefs used for ESP8266, Teensy…?
…
Will there be a define that can be used to ifdef in the libraries, like there are already ifdefs used for ESP8266, Teensy…?
But perhaps they are redundant
the underscores help their uniqueness, but i’m never sure whether it should be one or two of those.

stephen
I wonder if my drystone test results are correct as the show a 80MHz L476 is considerably slower than a 72MHz F103 ( albeit the F103 tests use libmaple and the L4 use STM’s HAL based core)
Perhaps an interrupt is wasting a lot of processing power, or the millis() isnt accurate on the L4 core
- STM32F103RBT6 STM32F303RET6 STM32F429ZIT6 STM32L476RG STM32F091RCT6 STM32L053R8T6
- STM32F103RBT6 STM32F303RET6 STM32F429ZIT6 STM32L476RG STM32F091RCT6 STM32L053R8T6
So perhaps this is the norm for Arduino cores. ( libmaple also uses systick for millis())
If systick is available, it seems the logical way to maintain a millisecond counter as there is no MCU CPU overhead for this operation.
I.e the MCU hardware prescales the master clock and then auto incremenets a register.
I wonder what other use systick is performing on the L4 core if its not counting millis()
I presume it must be doing something else, otherwise a general purpose timer is being wasted for millis() when it could be used for something else
Systick is not available on all ARM cores but all members of STM32 family have systick, so, it is not problem to use it globally.
Do the Cortex M0 also have it ?
I know the nRF51822 Cortex M0 does not have systick, but this is probably something to do with the nRF51 hardware and not that its a Cortex M0
Do the Cortex M0 also have it ?
I know the nRF51822 Cortex M0 does not have systick, but this is probably something to do with the nRF51 hardware and not that its a Cortex M0
That is a considerable amount of current for a low power device.
I dont suppose there is any point changing this for the Nucleo L4 but on the other boards, If Wi6 decide to use a timer for millis, I think we will probably end up changing it back to using systick
void TIM2_IRQHandler(void) {
if (TIM2->SR & TIM_SR_UIF)
{
Serial.println("TIM2 Interrupt");
}
TIM2->SR = 0; // reset the status register
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
delay(3000); // open your serial console already
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // enable TIM2 clock
TIM2->PSC = 36000; // clock speed should be 72MHz, so 72MHz/36000 = 2KHz
TIM2->ARR = 2000; // 2KHz clock/2000 = 1Hz so interrupt handler should run once a second
TIM2->DIER |= TIM_DIER_UIE; // enable update interrupt
NVIC_EnableIRQ(TIM2_IRQn); Serial.println("Interrupt set");
TIM2->CR1 |= TIM_CR1_CEN; // counter enabled
Serial.println("Timer 2 enabled");
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println(TIM2->CNT);
delay(50);
}
uint32_t apin = ulPin&0x0000000F;
1. Crash when using timers.
2. Limiting analog pins to low pin numbers
3. HAL_Delay not workinb correctly on the L4
Re:2
I guess this was put in for Nucleo boards. But i am not sure what purpose it performs, i.e it turns pin 16 into pin 0 etc
I am not sure what happens on an AVR Arduino board if you do an analogWrite on pin 16
I am using STM32F1xx Cores 2017.1.20 with an STM32 VL Discovery STM32F100RB. Having problems with using integrated DAC channels.
I’ve used both dac_write_value & analogWrite but with no results (code stucks or does nothing), even when i did some changes in g_current_init_id of analog.c
However, ADC functions work OK !!!
Think the DAC code is incomplete. What’s the situation ?
Thanks,
Nick
Afaik only HD mcus (from xC on) have DAC..
Also, there IS code inside analog.c …..
http://www.st.com/en/microcontrollers/s … tId=LN1565
and the high density version has DAC, i did have a stm32f103rbt6 board https://www.olimex.com/Products/Duino/S … INO-STM32/ as well, no DAC, the only good thing is more of the gpio and afio pins are broken out hence more functions are accessible compared to say stm32f103c8t6 or stm32f103cbt6 (the blue pill / maple mini)
Got a new nucleo 64 with an STM32F103RB (apart from the L476) and trying to port a program from an M4 TI Arm chip – same arduino framework…. Part of the code using serial for GPRS interfacing works OK. However i’m trying to find out Timer’s use and libs (not HAL) to help with this as -compared to the other ARM chip the timers low level use is much more complicated…
Any help with this ?
thanks
Thanks !
It’s planned to extend TIMER API.
Anyway, as @ChrisMicro shows in its example you could use directly the HAL to use a timer.
I’ve used HAL before but i had problems compiling with the callback function…
Off to try the code….
Nick
(Arduino IDE)
timer.c:(.text.TIM3_IRQHandler+0x0): multiple definition of `TIM3_IRQHandler’
sketch\sketch_nov07a.ino.cpp.o:sketch_nov07a.ino.cpp:(.text.TIM3_IRQHandler+0x0): first defined here
or VS Arduino
Timer1F030.ino:25:17: error: conflicting declaration of ‘void TIM3_IRQHandler()’ with ‘C’ linkage
Timer1F030.ino:previous declaration with ‘C++’ linkage
work is done in Nucleo F030RB with STM core…. i think the code you have is not with STM core….
as far as i remember i had similar problems with Timer handler declaration in the past…. first time i tried to use HAL for timers…
As a workaround, you can comment this one in the core:
https://github.com/stm32duino/Arduino_C … er.c#L1077
then it should be ok.
As said it will be extended and more user friendly.
there should be something, else why the compiler is complaining ???
i’ll give it a try…
void TIM3_IRQHandler(void)
{
if(timer_handles[2] != NULL) {
HAL_TIM_IRQHandler(timer_handles[2]);
}
}
where this file should be ?
In fact the error is that the TIM3_IRQHandler(void) is already defined in the core.
As it is a weak one, you should be able to comment it.
it also workd OK
code below
// for ARDUINO to compile
// timer.c in
// C:\Users\Nick\AppData\Local\Arduino15\packages\STM32\hardware\stm32\2017.8.31\cores\arduino\stm32
// commend TIM3_IRQHandler
static TIM_HandleTypeDef s_TimerInstance =
{
.Instance = TIM3
};
extern “C” void TIM3_IRQHandler(void)
{
static boolean flag = false;
static int32_t index = 0;
if (__HAL_TIM_GET_FLAG(&s_TimerInstance, TIM_IT_UPDATE) != RESET)
{
__HAL_TIM_CLEAR_IT(&s_TimerInstance, TIM_IT_UPDATE);
if (flag)
{
digitalWrite(LED_BUILTIN, HIGH);
flag=0;
}
else
{
digitalWrite(LED_BUILTIN, LOW);
flag=1;
}
}
}
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
HAL_NVIC_SetPriority( TIM3_IRQn, 0, 0 );
HAL_NVIC_EnableIRQ ( TIM3_IRQn );
s_TimerInstance.Init.Prescaler = 48000; //APB1 TIM3 has 48Mhz
s_TimerInstance.Init.CounterMode = TIM_COUNTERMODE_UP;
s_TimerInstance.Init.Period = 100-1; // prescaler gives 2khz time base
s_TimerInstance.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
s_TimerInstance.Init.RepetitionCounter = 0;
__HAL_RCC_TIM3_CLK_ENABLE();
HAL_TIM_Base_Init ( &s_TimerInstance );
HAL_TIM_Base_Start_IT ( &s_TimerInstance );
}
void loop()
{
}
TestF030.ino:31:17: error: conflicting declaration of ‘void TIM3_IRQHandler()’ with ‘C’ linkage
TestF030.ino:previous declaration with ‘C++’ linkage
Error compiling
Thing is VS is so much better / faster than Arduino IDE and (apart from this timer issue) works OK with ST nucleo boards….
still could not find the file that uses to change as did with arduino….
extern “C++” void TIM3_IRQHandler(void)
but in this case, code does NOT run !!!!!
Yes i’m not an experienced C++ programmer….
I put here the problem since i’m using STM core and not some other framework that handles timers in another way….
As far as i can see STM core does not have yet API for timer’s use but has internal definitions that pose problems even using HAL to have timer & interrupts… It seems to me the problem is not that easy to solve…
I don’t know somewhere else to put it since it refers only to STM core…. Have you something in mind ?
[nikosx – Tue Nov 07, 2017 9:14 pm] –
I don’t know somewhere else to put it since it refers only to STM core…. Have you something in mind ?
Yes start another thread in this forum subsection and title it: “Problems using STM core with Visual Studio 10”
The minute you mentioned this:
nikosx wrote:Ok…. Does NOT compile for VS 10 + VS Arduino but it did compile and run OK for ARDUINO IDE…
it also workd OK
Anyway, I’ve tested your sketch.
So, first issue is the multiple definition of the TIM3_IRQHandler.
I think the best fix is to define it as WEAK.
I’ve tested and it is ok.
extern “C” is mandatory to avoid any c++ function name decoration.
a) Where do you think should the topic be ?
b) I know extern “C” is mandatoty but where should the WEEK be put ?
thanks