Hello, some time ago I started to play with CortexM4,
I bought a Discovery Board with a STM32F407VG in order to be programmed with uVision from Keil.
I am developing a project where the money is very restricted, that's why I was using a free licence from Keil.
Everything was working fine until I exceed the program size of 32KB(now I need to pay the license if I want to continue for this way).
I started to look for other option, and gnu-arm-none-eabi with Eclipse seems to be the answer.
The big problem are the peripherals: I need to use UART(to output message on debugging time using the famous "printf()") and SDIO to log some variables from different sensors that require I2C.
In general terms: what are the aspects that I need to consider when I switch those IDEs: from uVision to "System Workbench for STM32" known as SW4STM32.
I think I can make this very easy for you, but you may need to start over.
First, I use ST's very nice initialization code generator CubeMX to get started. It gets rid of the need to hand modify all of the Standard Peripheral Driver stuff and will give you a much quicker way to get other stuff running like a USB port console, after you get the UART version working.
I use the SW4STM32 toolchain, Eclipse based, unrestricted, works fine.
Start with a blinky program. Just open CubeMX, select New Project, when the window comes up, change from the MCU to Board tab on the upper left and select the board you are using (DiscoF4 I think) and click OK at the bottom. All of the GPIO pins are already configured to talk to the LEDs so you just need to go to the Project menu at the top, select "Settings", enter a directory where you want your files, and a project name. DONT FORGET to change the Tool chain IDE from the default "EWARM" to SW4STM32. OK out of the settings then generate the code by either clicking on the "gear" icon at the top or select "Generate Code" from the same Project pulldown you just used for the project settings.
When it's done, open SW4STM32. Open File->Import, from the window that opens select General->Import Existing Project. In the new window browse to the containing directory you used for the project in CubeMX, it should find your Blinky project and click OK. Your priject should now show up on the left in the Project Explorer window. Expand it out, look in the Src directory and double click on the main.c file. Scroll down to the while(1){ clause, after the comment line /* USER CODE 3 BEGIN */ add the following two lines of code:
HAL_Delay(200);
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);
Save your changes, build the program, and right-click on the project name, select Debug As and Select AC6...
Hit run and the green LED should blink.
Now to do printf:
Same process but on the first CubeMX screen once you have your project settings set, on the left column find one of the UARTs you would like to use and enable it as Asynchronous. You can click the top tab to the Configuration view to check the baud rate. It is probably set to 115k, you can change it if you like, but regardless you'll want to know what it is when you fire it up.
Have CubeMX generate the code, import it the same way you did Blinky and you should be able to build it but it won't do much.
First I would just verify that the UART works by using the ST HAL calls to talk directly to the UART. If you are adding to you blink program and already have the endless loop with the Delay built in, just add the following line:
HAL_UART_Transmit(&huart2, "Hello There World\r\n",19, 3000);
Where the first parameter is the descriptor/handle that the init code created for you (near the top of your main() source code). It may be different if you picked another UART, not 2 or it might ne husart2, just find it in the source code). Next is the array of characters the HAL call will send to the UART and the next parameter is the number of bytes to send (I counted). Finally the HAL call takes a timeout value in milliseconds of when to give up if things don't work. I figure 3 seconds is ok for most cases. You need to connect the Tx pin of the UART to a UART-toUSB dongle like the FTDI chip based boards from a million Chinese manufacturers, and open a terminal emulator program on your PC like TeraTerm (my preference). Make sure you set the Serial Port settings to the right COM port for your dongle (you can find it in Device Manager) and set the baud rate to what you had in CubeMX. You should see your message displayed over and over again.
Once this is working it is a small step to get to full printf() support. You just need to add one OS callback routine which the libraries will look for when printf is invoked. The routine is int _write(int File, char *outstring, int len);
Put the function declaration somewhere at the top of the file in an appropriate place (like where the comments say something like user private function declarations). Then add at the very bottom of the file between the bracketed comments for USER CODE 4 this function:
int _write(int FD, char* outstring, int len){
while(HAL_UART_Transmit(&huart2, outstring, len, 3000) != HAL_OK);
return len;
}
The bracketing in the while clause makes sure that the HAL UART routine is ready for new data, and not busy. The _write function is well defined and documented. the first field is a device descriptor (number) indicating which open device this message is destined for. Since we have only one output device we can ignore it. The next two parameters are very nicely given to us by the printf() handler to be a formatted string and the length of the string. The function is supposed to return the number of characters written in case there is an error (like you were writing to a file, not the console and the disk was full before you finished). But if printf gets back the same number as it sent it is happy.
That should do it. If you want to get fancy later, you can use the Interrupt driven or DMA driven UART HAL calls but you'll need to enable them in CubeMX first.
Have fun and let me know if it works for you.
Aaron