FreeRTOS pour em::Blocks & STM32F4
Dans l’environnement em::Blocks, il est possible de créer des templates qui permettent d’initialiser facilement des nouveaux projets.
Cet article décrit comment créer un nouveau template pour em::Blocks contenant :
- FreeRTOS V8.12
- STM32F4xx HAL Driver (la nouvelle couche d’abstraction STM32CubeF4 de ST)
- La configuration spécifique pour la carte the STM32F4-Discovery
Installation du template téléchargé
Comme il est un peu long de créer ce template, vous pouvez l’installer directement dans em::Blocks à partir de la version téléchargée.
- Télécharger le template ICI ou sur mon repertoire GitHub
- Dézipper le fichier pour créer le répertoire « STM32F4-Discovery-Template »
- Copier « STM32F4-Discovery-Template » dans le répertoire Windows %AppData% pour em::Blocks en lançant la commande suivante :
xcopy /S /I STM32F4-Discovery-Template %APPDATA%\EmBlocks\2.00\UserTemplates\STM32F4-Discovery
Pour créer un nouveau projet dans em::Blocks, utilisez le menu « File / New / From template… » et sélectionnez le nouveau template. Ensuite sélectionnez le répertoire cible et entrez le nom du projet.
Comment créer ce template
Créez un nouveau projet comme décrit dans la première partie de l’article « Utiliser em::Blocks avec la STM32F4-Discovery« .
Nommez votre projet « STM32F4-Discovery » et ne pas faire la fin « Adaptation pour la STM32F4-Discovery ».
Ajout des fichiers à ce template
Créer un répertoire STM32F4 directory sous C:\
Dézipper le fichier stm32cube_fw_f4_v130.zip dans ce répertoire (voir l’article précédent pour le télécharger)
Télécharger et lancer le programme FreeRTOSV8.1.2.exe pour dézipper les fichiers dans ce répertoire
Le résultat pour ce répertoire STM32F4 est:
- FreeRTOSV8.1.2 : La distribution freeRTOS
- STM32Cube_FW_F4_V1.3.0 : Le firmware STM32Cube F4
- STM32F4-Discovery : Le nouveau projet créé pour réaliser ce template
Aller dans « STM32F4-Discovery » et supprimer le répertoire « SPL » qui contient l’ancien frimware.
Supprimer le contenu du répertoire « Inc ». Les fichiers seront remplacés par la version HAL.
Creation de la partie FreeRTOS
– Aller dans « c:\STM32F4\STM32F4-Discovery » (le répertoire de votre nouveau projet) et y créer le répertoire « Firmware ».
– Aller dans ce répertoire « Firmware » et y créer le répertoire « FreeRTOS ».
– Se positionner dans « FreeRTOS ».
– Copier les fichiers sources (*.c) de « c:\STM32F4\FreeRTOSV8.1.2\FreeRTOS\Source\*.c ».
– Copier les fichiers d’inclusion (*.h) de « c:\STM32F4\FreeRTOSV8.1.2\FreeRTOS\Source\include\*.h ».
– Copier le contenu de « c:\STM32F4\FreeRTOSV8.1.2\FreeRTOS\Source\portable\GCC\ARM_CM4F\*.* ».
Le fchier source de la gestion mémoire doit être ajouté (5 fichiers existent, consultez la documentation pour plus de détails).
– La première version convient dans la plus part des cas, donc copier le fichier « c:\STM32F4\FreeRTOSV8.1.2\FreeRTOS\Source\portable\MemMang\heap_1.c » dans ce répertoire « FreeRTOS ».
– Copier le fichier « c:\STM32F4\FreeRTOSV8.1.2\FreeRTOS\Demo\CORTEX_M4F_STM32F407ZG-SK\FreeRTOSConfig.h » dans ce répertoire « FreeRTOS ».
Un fichier supplémentaire doit être créé:
– Créer dans le répertoire « FreeRTOS » un fichier appelé « FreeRTOS-hook.c », l’éditer pour ajouter le code suivant :
#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( ;; ); } /*-----------------------------------------------------------*/
Création de la partie STM32CubeF4
– Remonter dans « c:\STM32F4\STM32F4-Discovery\Firmware »
– Copier le répertoire « STM32F4xx_HAL_Driver » situé dans « c:\STM32F4\STM32Cube_FW_F4_V1.3.0\Drivers ».
– Copier le répertoire « STM32F4-Discovery » situé dans « c:\STM32F4\STM32Cube_FW_F4_V1.3.0\Drivers\BSP ».
– Copier le répertoire « Components » situé dans « c:\STM32F4\STM32Cube_FW_F4_V1.3.0\Drivers\BSP ».
– Copier le répertoire « STM32_Audio » situé dans « c:\STM32F4\STM32Cube_FW_F4_V1.3.0\Middlewares\ST ».
– Se positionner dans le répertoire « c:\STM32F4\STM32F4-Discovery\inc »
– Copier le fichier « stm32f4xx_hal_conf.h » situé dans « c:\STM32F4\STM32Cube_FW_F4_V1.3.0\Projects\STM32F4-Discovery\Templates\Inc ».
– Copier le fichier « stm32f407xx.h » situé dans « c:\STM32F4\STM32Cube_FW_F4_V1.3.0\Drivers\CMSIS\Device\ST\STM32F4xx\Include ».
– Copier le fichier « stm32f4xx.h » situé dans « c:\STM32F4\STM32Cube_FW_F4_V1.3.0\Drivers\CMSIS\Device\ST\STM32F4xx\Include ».
– Copier le fichier « system_stm32f4xx.h » situé dans « c:\STM32F4\STM32Cube_FW_F4_V1.3.0\Drivers\CMSIS\Device\ST\STM32F4xx\Include ».
Configuration de em::Blocks IDE
– Dans la fenêtre de Workspace, faire un clique droit sur le projet STM32F4-Discovery et sélectionner « Build options… »
– Dans l’onglet « Compiler settings », sélectionner le sous onglet « #define ».
Ajouter les deux constantes STM32F407xx et USE_HAL_DRIVER
– Dans l’onglet « Compiler settings », sélectionner le sous onglet « Other options ».
Ajouter l’option -Wno-unused-but-set-variable et valider avec le bouton « Ok » (pour supprimer le warning: variable ‘xxx’ set but not used).
– Editer le fichier source « Source/src/system_stm32f4xx.c » et à la ligne 156 changer la valeur de #define PLL_M à 8 (Le Quartz est à 8Mhz).
– Faire un clique droit sur la racine « STM32F4-Discovery » dans la fenêtre Workspace. Sélectionner « Remove files… » et valider les 2 boites de dialogue suivantes pour supprimer tous les fichiers de l’arborescence projet.
– Faire un clique droit sur la racine « STM32F4-Discovery » et sélectionner « Add files recursively… » pour re-créer la nouvelle structure du projet :
* valider la première boite de dialogue pour inclure le contenu du répertoire « STM32F4-Discovery ».
* dans la seconde boite de dialogue, aller en bas de la liste des fichiers et cocher les deux derniers fichiers « stm32f407vg_flash.ld » et « stm32f407vg_sram.ld ». Ensuite cliquer sur « Ok »
* cliquer sur « Ok » à la troisième boite de dialogue.
(si vous avez un répertoire « D sources » dans l’arborescence projet, due à une complation précédente importée, ouvrez le et faites un clique droit sur le répertoire « obj », sélectionner « remove « obj\* »)
– Editer le fichier « Headers/Firmware/STM32F4-Discovery/stm32f4_discovery_audio.h » et à la ligne 52 remplacer #include « ..\..\..\Middlewares\ST\STM32_Audio\Addons\PDM\pdm_filter.h »
par « #include « pdm_filter.h »
– Editer le fichier « Header/Firmware/FreeRTOS/FreeRTOSConfig.h » et déplacer la ligne 85 en dehors du bloc « #ifdef __ICCARM__ ».
On doit avoir :
#ifdef __ICCARM__ #include <stdint.h> #endif extern uint32_t SystemCoreClock;
– Editer le fichier « main.c » pour remplacer le contenu par :
/* ** ** 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); } }
On peut maintenant compiler ce projet sans erreur.
Si on le lance, une première tâche fait cligotter la LED 6 avec une période de 1s et une seconde tâche recopie l’état du bouton utilisateur sur la LED 3.
Maintenant que le projet est prêt (et comme ça nous a pris pas mal de temps pour le construire 😉 ), il faut le sauver sous forme d’un template dans em::Blocks.
Utiliser le menu « File / Save Project as Template… »
Complément pour le STM32CubeF4 V1.9.0
– Se positionner dans le répertoire « c:\STM32F4\STM32F4-Discovery\cmsis ».
– Effacer son contenu
– Y recopier le contenu du réperoire « c:\STM32F4\STM32Cube_FW_F4_V1.9.0\Drivers\CMSIS\Include »