Thierry

COM port emulation with USB

It is possible to emulate a COM port with the USB OTG micro-AB connector.

usb

The USB communications device class (or USB CDC) is a composite Universal Serial Bus device class that is available in the STM32 Cube F4 HAL layer.

 

To test it, this example implements:

  • LED 5 is flashing with a period of 2 seconds (1 sec. on, 1 sec. off)
  • LED 4 represents the status of the user button (push or not)
  • USB OTG emulates a new COM port and echo all incoming characters

You can download the source code here or in my GitHub repository

To compile this source code in em::Blocks, you need to:

  1. Download the source files and unzip
  2. Open the project file “Usb-HAL.ebp”
  3. Check the constant definition USE_USB_FS is defined at the project level.

To do this check, right click on the project in the “management “windows, then select the “build Option…” option in the contextual menu.

USB_Constant

Click on the “Usb-Hal” in the left part of the dialog box to select the project global setting.

In the “#defines” tab of the compiler settings, check that USE_USB_FS is present.

 

Warning: There is a bug in the STM32 Cube F4 distribution files (corrected here)

In the usbd_cdc.c file, in the USBD_CDC_TransmitPacket() function, the update of the state is done after the call of transmit (that is using interrupts and also update the status).

USBD_LL_Transmit(...);
hcdc->TxState = 1;

So in case of small transmission (1 byte for example), the Transmit function can end before the function update the state with a wrong information. The solution: invert the two lines to indicate the Transmit before sending bytes.

hcdc->TxState = 1;
USBD_LL_Transmit(...);

FreeRTOS for em::Blocks & STM32F4-Discovery

In the em::Blocks EDI, it is possible to create templates in order to create easily new projects.

This post describes the way to create a new template for em::Blocks containing:

  • FreeRTOS V8.12
  • STM32F4xx HAL Driver (the STM32CubeF4 new hardware abstraction layers)
  • Specific configuration for the STM32F4-Discovery board

 

Installation of the downloaded template

As it is a bit long to create this template, you can install directly in em::Block the downloded version.

  1. Download the template here or in my GitHub repository
  2. Unzip the file to create the “STM32F4-Discovery-Template” directory
  3. Copy the “STM32F4-Discovery-Template” in the Windows AppData directory for em::Blocks by launching the following command:
xcopy /S /I STM32F4-Discovery-Template %APPDATA%\EmBlocks\2.00\UserTemplates\STM32F4-Discovery

To create a new project in em::Blocks, use the “File / New / From template…” menu and select the new template. Then enter the target directory and the project name.

 

How to create this template

Create a new project as described in the first part of the “Use em::Blocks with the STM32F4-Discovery” post.
Name your project “STM32F4-Discovery” and do not realize the “Adaptation for the “STM32F4-Discovery” part.

 

Add Files in this template

Create an STM32F4 directory in C:\

Unzip the stm32cube_fw_f4_v130.zip file in this directory (see previous post to download it)

Download and run the FreeRTOSV8.1.2.exe program to unzip file in this directory

The result for this STM32F4 directory is:

  • FreeRTOSV8.1.2 : The free RTOS distribution
  • STM32Cube_FW_F4_V1.3.0 : The STM32Cube F4
  • STM32F4-Discovery : The new project created to realize the template

Go to the “STM32F4-Discovery” directory and remove the “SPL” directory that contains the old firmware.
Delete the content of the “Inc” directory. Files will be replaced by the HAL versions.

Creation of the RTOS part

– Go to the “c:\STM32F4\STM32F4-Discovery” (your new project directory) and create a “Firmware” directory.

– Go to this “Firmware” directory and create a “FreeRTOS” directory.

– Go in this new “FreeRTOS” directory.

– Copy the source files (*.c) from “c:\STM32F4\FreeRTOSV8.1.2\FreeRTOS\Source\*.c”.

– Copy the Header files (*.h) from “c:\STM32F4\FreeRTOSV8.1.2\FreeRTOS\Source\include\*.h”.

– Copy the content of “c:\STM32F4\FreeRTOSV8.1.2\FreeRTOS\Source\portable\GCC\ARM_CM4F\*.*” in this FreeRTOS directory.

Memory management source file must be added (5 files exist, check the documentation for details).
– The first version is ok for most of cases, so copy the “c:\STM32F4\FreeRTOSV8.1.2\FreeRTOS\Source\portable\MemMang\heap_1.c” file in the FreeRTOS directory.

– Copy the “c:\STM32F4\FreeRTOSV8.1.2\FreeRTOS\Demo\CORTEX_M4F_STM32F407ZG-SK\FreeRTOSConfig.h” file in the FreeRTOS directory.

One more file is needed.
– Create in the directory “FreeRTOS” a file named “FreeRTOS-hook.c”, edit it to append the following code:

#include "FreeRTOS.h"
#include "task.h"
#include "stm32f4xx_hal.h"

void vApplicationTickHook( void )
{
    HAL_IncTick();
}
/*-----------------------------------------------------------*/

void vApplicationMallocFailedHook( void )
{
	/* vApplicationMallocFailedHook() will only be called if
	configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h.  It is a hook
	function that will get called if a call to pvPortMalloc() fails.
	pvPortMalloc() is called internally by the kernel whenever a task, queue,
	timer or semaphore is created.  It is also called by various parts of the
	demo application.  If heap_1.c or heap_2.c are used, then the size of the
	heap available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in
	FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used
	to query the size of free heap space that remains (although it does not
	provide information on how the remaining heap might be fragmented). */
	taskDISABLE_INTERRUPTS();
	for( ;; );
}
/*-----------------------------------------------------------*/

void vApplicationIdleHook( void )
{
	/* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
	to 1 in FreeRTOSConfig.h.  It will be called on each iteration of the idle
	task.  It is essential that code added to this hook function never attempts
	to block in any way (for example, call xQueueReceive() with a block time
	specified, or call vTaskDelay()).  If the application makes use of the
	vTaskDelete() API function (as this demo application does) then it is also
	important that vApplicationIdleHook() is permitted to return to its calling
	function, because it is the responsibility of the idle task to clean up
	memory allocated by the kernel to any task that has since been deleted. */
}
/*-----------------------------------------------------------*/

void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
{
	( void ) pcTaskName;
	( void ) pxTask;

	/* Run time stack overflow checking is performed if
	configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2.  This hook
	function is called if a stack overflow is detected. */
	taskDISABLE_INTERRUPTS();
	for( ;; );
}
/*-----------------------------------------------------------*/

 

Creation of the STM32CubeF4 part

– Go up to the “c:\STM32F4\STM32F4-Discovery\Firmware”

– Copy the “STM32F4xx_HAL_Driver” directory located in “c:\STM32F4\STM32Cube_FW_F4_V1.3.0\Drivers”.

– Copy the “STM32F4-Discovery” directory located in “c:\STM32F4\STM32Cube_FW_F4_V1.3.0\Drivers\BSP”.

– Copy the “Components” directory located in “c:\STM32F4\STM32Cube_FW_F4_V1.3.0\Drivers\BSP”.

– Copy the “STM32_Audio” directory located in “c:\STM32F4\STM32Cube_FW_F4_V1.3.0\Middlewares\ST”.

– Change to the “c:\STM32F4\STM32F4-Discovery\inc” directory

– Copy the “stm32f4xx_hal_conf.h” file located in “c:\STM32F4\STM32Cube_FW_F4_V1.3.0\Projects\STM32F4-Discovery\Templates\Inc”.

– Copy the “stm32f407xx.h” file located in “c:\STM32F4\STM32Cube_FW_F4_V1.3.0\Drivers\CMSIS\Device\ST\STM32F4xx\Include”.

– Copy the “stm32f4xx.h” file located in “c:\STM32F4\STM32Cube_FW_F4_V1.3.0\Drivers\CMSIS\Device\ST\STM32F4xx\Include”.

– Copy the “system_stm32f4xx.h” file located in “c:\STM32F4\STM32Cube_FW_F4_V1.3.0\Drivers\CMSIS\Device\ST\STM32F4xx\Include”.

 

Configuration of the em::Blocks IDE

– In the Workspace window, right click on the STM32F4-Discovery project and select “Build options…”

– In the “Compiler settings” tab, select the “#define” sub-tab.
Add the two constants STM32F407xx and USE_HAL_DRIVER

– In the “Compiler settings” tab, select the “Other options” sub-tab.
Add the option -Wno-unused-but-set-variable and validate with the “Ok” button (to remove the warning: variable ‘xxx’ set but not used).

– Edit the “Source/src/system_stm32f4xx.c” file and at line 156 change the value of the #define PLL_M to 8 (The Quartz is a 8Mhz).

– Right click on the “STM32F4-Discovery” root name in the Workspace window. Select “Remove files…” and validate the 2 next dialog boxes to remove all files from the project tree.

– Right click on the “STM32F4-Discovery” root name and select “Add files recursively…” to re-create the new project structure:

* validate the first dialog box to include the “STM32F4-Discovery” directory content.

* in the second Dialog, scroll to the end of the file list and check the 2 files “stm32f407vg_flash.ld” and “stm32f407vg_sram.ld”. Then click “Ok”

* click “Ok” on the third dialog box.

(if you have a “D sources” directory on the project tree due to a previous compilation imported, open it, right click on the “obj” directory, and select “remove “obj\*”)

– Edit the “Headers/Firmware/STM32F4-Discovery/stm32f4_discovery_audio.h” file and at line 52 replace #include “..\..\..\Middlewares\ST\STM32_Audio\Addons\PDM\pdm_filter.h”
by #include “pdm_filter.h”

– Edit the “Header/Firmware/FreeRTOS/FreeRTOSConfig.h” file and move the line 85 outside the “#ifdef __ICCARM__”.
It must be:

 
 #ifdef __ICCARM__
 #include <stdint.h>
 #endif
 extern uint32_t SystemCoreClock;

– Edit the “main.c” to change the content to:

/*
**
** Main.c
**
**
**********************************************************************/
#include "stm32f4xx.h"
#include "stm32f4_discovery.h"
#include "FreeRTOS.h"
#include "task.h"

#define TASK_PRIORITY	(tskIDLE_PRIORITY + 1)
#define STACK_SIZE      (configMINIMAL_STACK_SIZE + 100)


// Task prototypes
void LedTaskFunction( void *pvParameters );
void BtnTaskFunction( void *pvParameters );


int main(void)
{
    // Initialization
    HAL_Init();

    // create the task
    xTaskCreate( LedTaskFunction,   /* Pointer to the function that implements the task. */
                 "Flash Led",       /* Text name for the task. This is to facilitate debugging only. */
                 STACK_SIZE,        /* Stack depth */
                 NULL,              /* We are not using the task parameter. */
                 TASK_PRIORITY,     /* This task will run at priority 1. */
                 NULL );            /* We are not going to use the task handle. */

    // Create the BTN task
    xTaskCreate( BtnTaskFunction, "BTN Task", STACK_SIZE, NULL, TASK_PRIORITY, NULL );

    // Start the scheduler so the tasks start executing
    vTaskStartScheduler();

    while(1) ;
}

void LedTaskFunction( void *pvParameters )
{
    BSP_LED_Init(LED6);
    for (;;)
    {
        BSP_LED_Toggle(LED6);
        vTaskDelay(500);    // Delay 500 ms
    }
}

void BtnTaskFunction( void *pvParameters )
{
    BSP_LED_Init(LED3);
    BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_GPIO);
    for (;;)
    {
        if (BSP_PB_GetState(BUTTON_KEY))
            BSP_LED_On(LED3);
        else
            BSP_LED_Off(LED3);
    }
}

You can compile this project without error.

If you run it, a first task will flash the LED 6 with a 1s period and a second one will copy the state of the user button to the LED 3.

As this project is now ready (and takes long time to build 😉 ), save it as a template in em::Blocks.

Go to the “File / Save Project as Template…”

 

Change for the STM32CubeF4 V1.9.0

– Go to the directory “c:\STM32F4\STM32F4-Discovery\cmsis”.

– Delete the content

– Copy inside the content of the directory  “c:\STM32F4\STM32Cube_FW_F4_V1.9.0\Drivers\CMSIS\Include”

Use em::Blocks with the STM32F4-Discovery

After trying several IDE to program the STM32F4-Discovery card, I have selected the em::Blocks solution.

This is a free environment without code size limitation (unlike the free version of commecrial EDI). It is a fork of code::Blocks dedicated to embedded code generation. It manage out of the box numerous evaluation boards, including the STM32F4-Discovery card.

This software can be found in the download page of the site em::Blocks.

 

Prerequisits

– em:Blocks downloaded and installed  😉  The version used for this article is the V2.30

– STM32F4 drivers installed : can be downloaded on the ST Page (http://www.st.com/web/en/search/partNumberKeyword) and search the STSW-LINK reference (stsw-link008 for Windows 7 driver).

– Firmware for the STM32F4-Discovery card : on the same ST page, search for the STSW-STM32068 reference to download stsw-stm32068.zip file.

– Create a new working directory named “C:\STM32F4” and unzip stsw-stm32068.zip file inside. The result must be:
C:\STM32F4\STM32F4-Discovery_FW_V1.1.0

 

New project creation

 

Creation of the base cade

1) Launch em::Blocks. Open the menu “File / New / Project…”
2014-12-31_100609
2) Select “STmicro-ARM”

 

2015-01-03_171645
3) Enter the project name and the path

 

2014-12-31_100622
4) keep the default options

 

2014-12-31_100627
5) Select Cortex M4 (F3xx-F4xx)

 

2014-12-31_100632
6) Select STM32F4xx

 

2014-12-31_100659
7) Select STM32F407VG

 

2014-12-31_100713
8) Keep the default configuration

 

2015-01-03_170518
9) Select “Target settings” tab and check “Run to main()”. It allows the debugger to stop on the frist program line instead of the first assembler line of the loader.

==> The code is now generated.

 

Adaptation for the STM32F4-Discovery

1) Copy the firmware in the project directory :
copy c:\STM32F4\STM32F4-Discovery_FW_V1.1.0\Utilities\STM32F4-Discovery
to c:\STM32F4\Test

 

2) Import modifications in the projet

2014-12-31_102457

In the left window (project structure), right click on the project name. In the contetual menu select “Add files recusrsively”.

3) Sélect the new directory (we have just copied) to add it in the project

2015-01-03_172641

4) Validate the 2 dialog boxes that indicate the files to import

2015-01-03_173859 2014-12-31_101723

5) To avoid to include other dependencies, we need to remove the “audio” management files

2015-01-03_174657

 

Open the STM32F4-Discovery directory in the project window (left window).
Right click on the “”stm32f4_discovery_audio_codec.c” file and select “Remove file from project” to remove it (the file can also be deleted from the disc, but not mandatory).

 

5) Take in account the 8Mhz quartz

In the src directory, edit the file system_stm32f4xx.c

It is a configuration file that is automatically called during the boot phase. Contrary to what is indicated in the comment line 59, the crystal frequency is 8MHz. We need to change the PLL_M value to 8.

Edit the line 156 (or search the PLL_M constant) and change the value to 8:

#define PLL_M   8

 

6) The projet is now ready to compile.

For tests, I suggest you the following code for the main.c :

#include “stm32f4_discovery.h”

int main(void)
{
STM_EVAL_LEDInit(LED3);
STM_EVAL_LEDOn(LED3);
while(1) ;
}

In case of compil error related to the “audio” file, juste delete the “c:\STM32F4\Test\obj\Debug” rirectory and relaunch the compilation.

 

 Template generation

In order to redo this work for each new project, it is possible to create a project template.
By using this project that is correctly configurated, open the “File / Save project as template…” menu and just select a name for this template.

 

For new projects, just use the menu “File / New / From Template…” and select your template in order to have the default configuration applied. 🙂

STM32F4-Discovery presentation

It is a card with a lot of possibilities and a small price (about $15). If we compare with the Ardruino cards, this card is much more efficient for the same price.

M-05313

STM32F4-Discovery Key Features:

  • STM32F407VGT6 microcontroller featuring 32-bit ARM Cortex-M4F core, 1 MB Flash, 192 KB RAM in an LQFP100 package
  • On-board ST-LINK/V2 with selection mode switch to use the kit as a standalone ST-LINK/V2 (with SWD connector for programming and debugging)
  • Board power supply: through USB bus or from an external 5 V supply voltage
  • External application power supply: 3 V and 5 V
  • LIS302DL or LIS3DSH ST MEMS 3-axis accelerometer (LIS3DSH on last versions)
  • MP45DT02, ST MEMS audio sensor, omni-directional digital microphone
  • CS43L22, audio DAC with integrated class D speaker driver/li>
  • Four user LEDs, LD3 (orange), LD4 (green), LD5 (red) and LD6 (blue)
  • Two push buttons (user and reset)
  • USB OTG FS with micro-AB connector to interface externes systeme (USB key, PC, …)
  • Extension header for all LQFP100 I/Os for quick connection to prototyping board and easy probing

For more details, you can consult the publisher’s link: STM32F4-Discovery