As stated in their tagline, CooCox is a set of "Free and Open ARM Cortex MCU Development Tools." CoIDE is an Eclipse based integrated development enviroment supporting the standard GCC ARM tool set: compiler, assembler, linker, and debugger. The STM32 discovery boards include an embedded ST-LINK or ST-LINK/V2 which is supported by CoIDE for flashing and debugging. The real value add by CoIDE is point and click choice of MCU library modules for various peripherals, with hypertext library references and examples. CooCox supports a variety of ARM Cortex MCUs from various manufacturers. ST is just one of the manufacturers.
Here I will show you how to install CoIDE and essential dependencies to develop a simple Hello World program for the STM32 Value line discovery board. The steps are very similar for the other boards (except STM32-F3 is not directly supported at this time). The program will display debug output from printf() through the ST-LINK to the IDE's console window. This is the essential first program to see results from a program running on an embedded board. And it's not just a blinking LED, though we'll do that too.
One time installation and configuration.
1. Download ARM GCC2. Download CoIDE
3. Download STM32 ST-LINK Utility
3. Install ARM GCC
4. Install CoIDE
5. Configure CoIDE to point to ARM GCC
6. Install STM32 ST-LINK Utility
7. Plug in USB cable from PC to ST-LINK on discovery board
Creating your first project.
1. Click Create Project, name it hello2. When prompted Chip or Board, choose Chip
3. Choose ST, and STM32F100RB. Click Finish
4. In the Repository window, click on Semihosting and GPIO. Required dependencies will autoselect
5. Double click on main.c in the Project window, and modify to contain
#include <stdio.h>
#include <stm32f10x_gpio.h>
#include <stm32f10x_rcc.h>
int main(void)
{
GPIO_InitTypeDef gpio;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_StructInit(&gpio);
gpio.GPIO_Pin = GPIO_Pin_9; // Green LED
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
gpio.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &gpio);
gpio.GPIO_Pin = GPIO_Pin_8; // Blue LED
GPIO_Init(GPIOC, &gpio);
printf("Hello World!\r\n");
while(1)
{
static int count=0;
static int i;
static int led_state=0;
for (i=0; i<1000000; ++i);
GPIO_WriteBit(GPIOC, GPIO_Pin_9, led_state ? Bit_SET : Bit_RESET);
led_state = !led_state;
GPIO_WriteBit(GPIOC, GPIO_Pin_8, led_state ? Bit_SET : Bit_RESET);
printf("%d\r\n", ++count);
}
}
6. Open printf.c from the Project window
7. Add #include <semihosting.h> after the other includes.
8. In the PrintChar method, add the following line before the closing brace
SH_SendChar(c);
9. Right click on hello in tree of Project Window and choose Configuration
10. Navigate to Debugger tab, and verify ST-Link is chosen
11. Click on Semihosting Enable
12. Choose Project + Build, should be successful
13. Choose Debug + Debug, will deploy to board and stop at top of main
what changes are to be done if using the STM32F4 instead?
ReplyDelete// STM32F4DISCOVERY
ReplyDelete#include
#include
#include
int main(void)
{
GPIO_InitTypeDef gpio;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_StructInit(&gpio);
gpio.GPIO_Pin = GPIO_Pin_12; // Green LED
gpio.GPIO_Mode = GPIO_Mode_OUT;
gpio.GPIO_Speed = GPIO_Speed_2MHz;
gpio.GPIO_OType = GPIO_OType_PP;
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOD, &gpio);
gpio.GPIO_Pin = GPIO_Pin_15; // Blue LED
GPIO_Init(GPIOD, &gpio);
printf("Hello World!\r\n");
while(1)
{
static int count=0;
static int i;
static int led_state=0;
for (i=0; i<1000000; ++i);
GPIO_WriteBit(GPIOD, GPIO_Pin_12, led_state ? Bit_SET : Bit_RESET);
led_state = !led_state;
GPIO_WriteBit(GPIOD, GPIO_Pin_15, led_state ? Bit_SET : Bit_RESET);
printf("%d\r\n", ++count);
}
}
Correction to last comment. The three includes for STM32F4 should be stdio.h, stm32f4xx_gpio.h and stm32f4xx_rcc.h
ReplyDeleteDave,
ReplyDeleteyour tutorial is a very good start with CooCox and STM32 Discovery boards.
I tried your example with my STM32F4 DISCOVERY and it worked fine.
Since I already had a small test code for this board written for Keil uVision4 (evaluation, 32k limited), I tried moving its source files to CooIDE. It compiled fine.
But I noticed that the initialization code in source file system_stm32f4xx.c is not executed.
What I care now is setting FLASH->ACR, which I found in system_stm32f4xx.c.
Then I noticed that in Project Configuration, Link,
"don't use the standard system startup files" is ticked.
I tried removing the tick mark, but build failed with a long list of errors like
error: ..\obj\startup_stm32f4xx.o uses VFP register arguments, hello.elf does not
Am I tampering with the project the wrong way?
Thanks
I would recommend starting from a CooIDE created project started from scratch and merge in your other project a file at a time. Only bring over the .c files. Probably don't bring over the .elf and .o files from the other compiler in case they wouldn't cooperate.
ReplyDeleteGood luck! Some tinkering will be required but you can get it!
Hi Dave,
ReplyDeleteI have a STM32F407VG Discovery Board plugged into a BB. I tried an example in CooIDE then found your tutorial and completed the steps with the added modification of the code for STM32F4. I still have the ST preloaded example running on the board. The tutorial gives an error of:
C:\CooCox\CoIDE>"C:/CooCox/CoIDE/bin\coflash.exe" program STM32F407VG "C:/CooCox/CoIDE/workspace/hello/hello/Debug/bin/hello.elf" --adapter-name=ST-Link --port=SWD --adapter-clk=1000000 --erase=affected --driver="C:/CooCox/CoIDE/flash/STM32F4xx_1024.elf"
Error: Connect failed, check config and cable connection
Program Download Failed !
I am a first time user. Please could you help. Thanks.
Hi Dave,
ReplyDeleteAlthough I thought the driver was installed in fact it wasn't. I used:
To upgrade ST-Link over STM32F4 Discovery
1. Select JTAG mode in setting of STM32 ST-LINK Utility
(Select "JTAG", from menu "Target->Settings->Connexion Protocol")
2. Disconnect and reconnect the target and execute "Firmware update" from "ST-LINK" menu
3. When the upgrad is over, Restore the setting to "SWD"
The disconnect and reconnect needed plugging the USB plug. Now I have completed your tutorial! Many thanks for your blog. Regards Kevin.
hi , I'm new and i don't know how to solve this problem :
ReplyDelete"BUILD FAILED
Output filename conflict: stm32f4xx_rcc.o would be produced from C:\CooCox\CoIDE\workspace\testled\STM32F4xx_StdFramework_V1.0_2013_03_15\StdPeriphLib\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_rcc.c and stm32f4xx_rcc.c
Total time: 0 seconds"
Hi benfraj elmokhtar - looks like the output file (stm32f4xx_rcc.o) already exists. Try to do a Project + Clean first, or start from scratch. More help may be available at the CooCox forums.
ReplyDeleteThanks :D , it's solved ;)
DeleteThanks Dave, this is a great tutorial - it helped me get started.
ReplyDeleteI did notice that I am not able to print floats to the debug window, so I wrote a simple function to do it (it might need tweaking if you want to print very small or large numbers)...
void printfloat(float f_num, int dplaces)
{
int p = 1;
int i;
for (i = 0; i < dplaces; i++){p*=10;}
printf("%d.%d",(int)floor(f_num),(int)round(p*(f_num-floor(f_num))));
}
Oh, I forgot to say that you will need the following line at the top of the file...
Delete#include < math.h >
and that you need to add m to the Linked Libraries box in the Link tab in the project configuration - this is to include the maths library for the floor() and round() functions.
Hello, Dave.
ReplyDeleteIt is my first experience of programming a µC.
I get "Unresolved inclusion: " . I don´t know how to fix it.
I installed STM32 ST-LINK Utility on my C-drive but then I moved the whole folder to D-drive to the same folder where I have installed my CooxIDE.
/ Unresolved inclusion: /
ReplyDeleteNon of header files can be included
Thanks for the tutorial. I had an error that I fixed by modifying core_cm3.c. After that all was good.
ReplyDeleteHi.
ReplyDeleteGreat tutorial.
Unfortunetaly i've got a problem. I Did everything u said and when i right-click on project to select Configuration i CoIDE crashes :< Dunno why. Maybye u know what couses this problem?
Sorry, haven't seen that problem. You may want to check with the CoIDE forums.
DeleteOk, i worked it out.
DeleteReconnecting the board helped :d
Now i got aanother problem - with compiler.
I can't build project, and i found out that I can't set the same toolchain path as here http://www.coocox.com/CoIDE/Compiler_Settings.html after the GCC ARM Embedded installation. What am I doing wrong?
Common issue is pointing to the wrong folder. UI will refuse to let you set it to the wrong place, but gives a hint that a certain executable must be present there. Mine is set to:
DeleteC:\Program Files (x86)\GNU Tools ARM Embedded\4.7 2013q1\bin
Thx for advice and patience. That helped :D
DeleteBut now, when I'm building, an error shows up:
Error: registers may not be the same -- `strexb r3,r2,[r3]
Can't help you there. Sorry!
DeleteOk, works. Solution:
Deletehttp://www.cesareriva.com/fix-registers-may-not-be-the-same-error/
Thanks for the follow up. Someone else had that error and mentioned a fix, and now it all makes sense. Hope this reference helps others too. Google search is a great resource right? Otherwise how did you find your way here? :-)
DeleteHi, I'd like to explain a bug I had and corrected. I'm using a STM32f100RB ST-Link device:
ReplyDeleteI followed all the instructions as described above and had the following error at compilation:
[cc] C:\Users\SBASTI~1\AppData\Local\Temp\ccLngF0b.s:772: Error: registers may not be the same -- `strexb r3,r2,[r3]'
[cc] C:\Users\SBASTI~1\AppData\Local\Temp\ccLngF0b.s:818: Error: registers may not be the same -- `strexh r3,r2,[r3]'
After looking on the web, it appears it is an error in the CMSIS implementation file core_cm3.c. Two functions are badly implemented: STREXB and STREXH. The bug is easily corrected by replacing the initial code by the following (just add the & caracter):
uint32_t __STREXB(uint8_t value, uint8_t *addr)
{
uint32_t result=0;
__ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
return(result);
}
uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
uint32_t result=0;
__ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
return(result);
}
Now everything works as expected !
For the STM32F0-discovery board (STM32F051) change the following:
ReplyDelete/* RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
/* gpio.GPIO_Mode = GPIO_Mode_Out_PP; */
gpio.GPIO_Mode = GPIO_Mode_OUT;
gpio.GPIO_OType = GPIO_OType_PP;
Thanks for taking the time to write this up. It has save me a ton of time.
-H
Thanks for the great post. I am using eclipse and tried to utilize semihosting library files with STM32F0Discovery. I enabled semihosting in eclipse and I could build it after minor changes in the code. Everything seems to be fine except SH_DoCommand function defined in SH_cmd.s file. I get "no source for SH_DoCommand()" message during debug process. HAs anybody got it worked in eclipse?
ReplyDeleteHi Dave.
ReplyDeleteThis tutorial is very useful and precise.
I want to use this CoIDE tool to move projects to Linux using Makefile.
Hopeful someday, Coocox will have a Linux port.
We need something that good and open source over in Linux world!
Thank you very much for making my transition and leaning esay,
Mike
Thank you very much for "printf" in semihosting !!!
ReplyDeleteThank you so much for this guide! may i ask regarding this issue im encountering when Im using the LCD drivers?
ReplyDeleteerror: unknown type name 'xtBoolean'
I have already have the xhw_types.h in the projects but still getting this error.
Sorry Patrick, I am not familiar with that type and error.
DeleteHi,
ReplyDeletei tried this code for blinking led. But it didn't work. Can you help me. i share tihs code.
#include
#include "stm32f2xx_gpio.h"
#include "stm32f2xx_rcc.h"
int main(void)
{
GPIO_InitTypeDef gpio;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);
gpio.GPIO_Pin = GPIO_Pin_14;
gpio.GPIO_Mode = GPIO_Mode_OUT;
gpio.GPIO_Speed = GPIO_Speed_2MHz;
gpio.GPIO_OType = GPIO_OType_PP;
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOD,&gpio);
printf("Hello World! \r\n");
while(1)
{
GPIO_WriteBit(GPIOD, GPIO_Pin_14,Bit_SET);
}
}
When you want to flash an LED in a loop, you usually need to have code that turns the LED off, turns the LED on, and delays in between each change. I only see one of these three in your code. Review my original code again that has these elements.
Deletethanks for the excellent tutorial dave ant it helped me a lot.
ReplyDeletei ran into problem when i wanted to print a double number type or a float
printf("%f \r\n", ADCResult/2.6 );
i do not get anything printed when in debugging. please help.
thanks
thanks
ReplyDeleteRan through the demo again today, almost 3 years later. Note that to enable Semihosting, the Debugger tab is within the Configuration View while not running. That is where you have to click on "Semihosting Enable" before printf will be redirected to the Semihosting window. Also it was necessary to upgrade the firmware on the STM32F4DISCOVERY board using the ST-Link Desktop application.
ReplyDeleteTested with
Delete* CooCox CoIDE version 1.78
* GNU Tools ARM Embedded 5.2 2015q4
* STM32 ST-Link v3.6.0
* STM32F4DISCOVERY, ST-Link firmware V2.J23.S0
Good tutorial. Thanks
ReplyDeleteGood tutorial. Thanks
ReplyDeleteHello, I need to make "snake game" in 8x8 matrix display and using STM32F407VG.Its very important for my graduation.Is there anyone who can help me?
ReplyDeleteplease suggest this code for lpc1768
ReplyDelete