Stm32f4 and Freertos
Stm32f4 and Freertos
• On some stm32 is periphery called ITM, not mix with ETM(real trace)
• This periphery can be used to internal send data from MCU over SWO pin
• And also some IDEs can display this information during debug
• Video: Link
Using SWO 4
• To make SWO working you musty connect the PA3 and Debugger SWO pin
together
Connect SWO
and PA3
Connect SWO
and PA3
Using SWO for printf 5
• If the MCU run on very high frequency and you not see print f output
you may try put into ITM send delay loop
/* USER CODE BEGIN 4 */
/*send text over SWV*/
int fputc(int ch, FILE *f) {
uint32_t i=0;
for(i=0;i<0xFFFF;i++);//waiting method, lower value will stop the SWV
ITM_SendChar(ch);//send method for SWV
return(ch);
}
/* USER CODE END 4 */
Using SWO for printf in KEIL 9
• In KEIL 1. Target
options 2. Select
DEBUG tab
• Open target options
(ALT+F7)
3. Set ST-Link
• Set ST-Link debugger
4. Open Settings
• Button Settings
6. Go to Trace tab
• Set SW(D)
in Debug TAB
5. Set SW(D)
• Got to Trace TAB
Using SWO for printf in KEIL 10
4. Button OK
Using SWO for printf in KEIL 11
• Button OK
• Open SWO
Using SWO for printf in IAR 14
• Enable
ITM Port 0
to terminal
• Button OK
Override clock and set
correct value (168MHz)
Enable ITM Port 0
• Run program
FreeRTOS
FreeRTOS
17
About FreeRTOS
• Market leading RTOS by Real Time Engineers Ltd.
• The following table lists examples of the CMSIS-RTOS APIs and the FreeRTOS APIs
used to implement them
• Middleware components using the CMSIS-RTOS API are RTOS agnostic, this
allows an easy linking to any third-party RTOS
• In Configuration TAB
is now possible to
configure FreeRTOS
Parameters
CubeMX FreeRTOS Configuration 26
• Config parameters
• Set kernel
• Mem setup
• Include parameters
• Include some additional functions,
not necessary for FreeRTOS run
• Use preemption
• If enabled use pre-emptive scheduling
Priority level
Create Task2 Task2 suspend
High priority
Task2
time
time
FreeRTOS
Memory allocations types
FreeRTOS
29
Dynamic memory management
• FreeRTOS have own heap which is use for components
• Tasks
• Queues
• Semaphores
• Mutexes
• Dynamic memory allocation
Heap Heap
pvPortMalloc
Allocated vPortFree
block 1
pvPortMalloc
Allocated vPortFree
block 2
pvPortMalloc
Allocated vPortFree
block 2
FreeRTOS
31
Dynamic memory management
• Heap_2.c
• Implements a best fit algorithm for allocation
• Allows memory free operation but does not combine adjacent free blocks => risk of
fragmentation
Allocated Allocated
pvPortMalloc vPortFree Heap 4
block 1 block 1
Allocated Heap 2
pvPortMalloc vPortFree Heap 2
block 2
Allocated Heap 3
pvPortMalloc vPortFree Heap 3
block 2
FreeRTOS
32
Dynamic memory management
• Heap_3.c
• Implements a simple wrapper for the standard C library malloc() and free(), the
wrapper makes these functions thread safe, but makes code increase and not
deterministic
pvPortMalloc
Allocated vPortFree
Allocated vPortFree
block 1 block 1
pvPortMalloc
Allocated vPortFree
block 2 Heap 2
pvPortMalloc
Allocated vPortFree
block 2
Memory allocation 34
• Use heap_4.c
• Memory allocation
void StartTask1(void const * argument)
{
/* USER CODE BEGIN 5 */
osPoolDef(Memory,0x100,uint8_t);
PoolHandle = osPoolCreate(osPool(Memory)); Create memory pool
uint8_t* buffer=osPoolAlloc(PoolHandle);
/* Infinite loop */ Allocate memory from pool
for(;;)
{
osDelay(5000);
}
/* USER CODE END 5 */
}
FreeRTOS
Tasks
FreeRTOS
36
Task states
• Ready
• Tasks are ready to execute but are Suspend
not currently executing because a
different task with equal or higher
osThreadSuspend
priority is running osThreadSuspend
osThreadResume
• Running
• when task is actually running osThreadCreate
Ready Scheduler Runing
osThreadSuspend
• Blocked
• Task is waiting for a either a
temporal or external event Event
• SysTick timer
• Used to periodically trigger
scheduling
FreeRTOS OS interrupts 38
Other IRQs
SVC
PendSV
SysTick
time
FreeRTOS
39
Stack pointer
• Main stack pointer
• Used in interrupts
• Allocated by linker during compiling
PendSV interrupt
Task 1 Task 2
• Create task
osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument)
• Delete task
osStatus osThreadTerminate (osThreadId thread_id)
• Get task ID
osThreadId osThreadGetId (void)
• Create Task
/* Create the thread(s) */
/* definition and creation of Task1 */
osThreadDef(Task1, StartTask1, osPriorityNormal, 0, 128);
Task1Handle = osThreadCreate(osThread(Task1), NULL);
Tasks API 41
• Resume task
osStatus osThreadResume (osThreadId thread_id)
• Suspend task
osStatus osThreadSuspend (osThreadId thread_id)
• Task is defined by
• Name
• Priority
• Stack size
• Name of entry function
• Task must have inside infinity loop in case we don’t want to end the task
time
Task1 Task1
Runing Runing Runing Runing Runing Runing
Task2 Task2
Task1
Ready Ready Ready Ready Ready Ready
Task2 Task2
Task1 Task1
Blocked Blocked Blocked Blocked Blocked Blocked
Task2 Task2 Task1
• Use HAL_Delay
Priority level
SysTick SysTick SysTick SysTick SysTick
High priority
time
Task1 Task1
Runing Runing Runing Runing Runing Runing
Task2 Task2 Task1
Task1 Task1 Task1
Ready Ready Ready Ready Ready Ready
Task2 Task2 Task2 Task2
• Button OK
Tasks lab 50
• Because task have high priority it allow to run lower priority task
/* USER CODE END 4 */
void StartTask1(void const * argument)
{
/* USER CODE BEGIN 5 */
uint32_t i = 0;
/* Infinite loop */
for(;;)
{
for (i = 0; i < 5; i++){
printf("Task 1\n");
HAL_Delay(50); Helps not spam terminal
}
osDelay(1000);
} Block task
/* USER CODE END 5 */
}
Tasks lab 51
• If higher priority task is not running we can print text from this task
/* StartTask2 function */
void StartTask2(void const * argument)
{
/* USER CODE BEGIN StartTask2 */
/* Infinite loop */
for(;;)
{
printf("Task 2\n"); Helps not spam terminal
HAL_Delay(50);
}
/* USER CODE END StartTask2 */
}
Tasks lab 52
Priority level
osDelay Delay end osDelay Delay end osDelay
High priority
time
Task1 Task1
Runing Runing Runing Runing Runing Runing
Task2 Task2 Task1
Task1
Ready Ready Ready Ready Ready Ready
Task2 Task2 Task2 Task2
Task1 Task1
Blocked Blocked Blocked Blocked Blocked Blocked
• Delay function
osStatus osDelay (uint32_t millisec)
Task 1 - Pri 1
Task 2 - Pri 2
Task 2
Delay end
Delay time
osDelayUntil 55
vTaskDelay
Until
PendSV vTaskDelay PendSV(idle)
Task 2
Delay end
DelayUntil time
osDelay and osDelayUntil 56
/* StartTask2 function */
void StartTask2(void const * argument)
{
/* USER CODE BEGIN StartTask2 */
/* Infinite loop */
for(;;)
{
printf("Task 2\n");
HAL_Delay(200);
}
/* USER CODE END StartTask2 */
}
osDelay and osDelayUntil 57
Task 1 - Pri 6
Task 2 - Pri 4
Task 1 - Pri 1
Task 2
xTaskCreate PendSV vTaskDelay PendSV(idle)
Pri 2
• Create Queue:
osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id)
• osEvent structure
typedef struct {
osStatus status; ///< status code: event or error information
union {
uint32_t v; ///< message as 32-bit value
void *p; ///< message or mail as void pointer
int32_t signals; ///< signal flags
} value; ///< event value
union {
osMailQId mail_id; ///< mail id obtained by \ref osMailCreate
osMessageQId message_id; ///< message id obtained by \ref osMessageCreate
} def; ///< event definition
} osEvent;
• Queue part
• Button Add
• Button OK
Queue lab 70
• Queue item type initialization, length definition and create of queue and
memory allocation
/* Create the queue(s) */ Queue item definition
/* definition and creation of Queue1 */
osMessageQDef(Queue1, 256, uint8_t);
Queue1Handle = osMessageCreate(osMessageQ(Queue1), NULL);
Queue size
Queue lab 71
• Sender1 task
void StartSender1(void const * argument)
{
/* USER CODE BEGIN 5 */
/* Infinite loop */
for(;;) Put value ‘1’ into queue
{
printf("Task1\n");
Item to send
osMessagePut(Queue1Handle,0x1,200);
printf("Task1 delay\n"); Timeout for send
osDelay(1000);
} Queue handle
/* USER CODE END 5 */
}
Queue lab 72
• Teceiver task
/* StartReceiver function */
void StartReceiver(void const * argument)
{
/* USER CODE BEGIN StartReceiver */
osEvent retvalue;
/* Infinite loop */
for(;;) Get item from queue
{
printf("Task2\n"); How long we wait on data in
retvalue=osMessageGet(Queue1Handle,4000); queue
printf(“%d \n",retvalue.value.p); It will Block task
}
/* USER CODE END StartReceiver */ Queue handle
}
Queue Blocking 73
• If any data are not in queue the task I blocked for settable time
Sender1- Pri 1
Receiver- Pri 1
• Same priorities
Two senders lab 76
• Simple receiver
/* StartReceiver function */
void StartReceiver(void const * argument)
{
/* USER CODE BEGIN StartReceiver */
osEvent retvalue;
/* Infinite loop */
for(;;)
{
retvalue=osMessageGet(Queue1Handle,4000);
printf("Receiver\n");
printf("%d \n",retvalue.value.p);
}
/* USER CODE END StartReceiver */
}
Two senders lab 78
• Because tasks have same priority, receiver will get data from queue after both
task put data into queue
Receiver Sender1
Pri 1 Pri 1
• Receiver is now unblocked every time when sender tasks put data into queue
Sender1- Pri 1
Sender2- Pri 1
Receiver- Pri 2
Sender1 Receiver
Pri 1 Pri 2
• Regenerate project
Queue items lab 82
• Two types
• Binary semaphores
• Counting semaphores
• Binary semaphore
• Have only one ‘token’
• Using to synchronize one action
• Counting semaphore
• Have multiple ‘tokens’
• Synchronize multiple actions
Binary Semaphore 88
Task1 Task2
Blocked
osSemaphoreWait
Task1 Task2
Blocked
osSemaphoreRelease osSemaphoreWait
Task1 Task2
Blocked
osSemaphoreWait
Task1 Task2
osSemaphoreRelease
Task1 Task2
osSemaphoreWait
Binary Semaphore 89
• Semaphore creation
osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count)
• Semaphore release
osStatus osSemaphoreRelease (osSemaphoreId semaphore_id)
Return Semaphore
status handle
Binary Semaphore lab 90
• Button Add
• Set parameters
• Button OK
Binary Semaphore lab 91
• Button Add
• Set name
• Button OK
Binary Semaphore lab 92
Task1 - Pri 1
Task2 - Pri 1
• Semaphore creation
/* Create the semaphores(s) */
/* definition and creation of myBinarySem01 */
osSemaphoreDef(myBinarySem01);
myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1);
Binary Semaphore lab 94
• Semaphore use
• Semaphore Wait
• Semaphore creation
osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count)
• Semaphore release
osStatus osSemaphoreRelease (osSemaphoreId semaphore_id)
Counting Semaphore 97
osSemaphoreRelease
osSemaphoreRelease
• Button Add
• Set parameters
• Button OK
Counting Semaphore lab 99
• Button Add
• Set name
• Button OK
Counting Semaphore lab 100
Task3 Task1
Pri 1 Pri 1
Task1 Task1
osMutexWait Resource
Resourse Resourse
Resource
Task2 Task2
Blocked Blocked
osMutexWait osMutexWait
Task1 Task1
osMutexRelease Resourse
Resource Resourse
Resource
Task2 Task2
Blocked
osMutexWait osMutexRelease
Mutex 105
• Mutex creation
osMutexId osMutexCreate (const osMutexDef_t *mutex_def)
Mutex Mutex
handle definition
• Wait for Mutex release
osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec)
• Mutex release
osStatus osMutexRelease (osMutexId mutex_id)
Return Mutex
status handle
Mutex lab 106
• Button Add
• Set parameters
• Button OK
Mutex lab 107
• Create Mutex
• Button Add
• Set name
• Button OK
Mutex lab 108
Task1- Pri 1
Task2- Pri 1
Task1 Task2
Pri 1 Pri 1
• Mutex creation
/* Create the mutex(es) */
/* definition and creation of myMutex01 */
osMutexDef(myMutex01);
myMutex01Handle = osMutexCreate(osMutex(myMutex01));
Mutex lab 110
• Semaphore use
• Are not precise but can handle periodic actions or delay actions
• Two modes
• Periodic
• One Pulse
Task1 Software
Timer Callback
osTimerStart
Return
Timer handle
status
Software Timers lab 115
• FreeRTOS configuration
• Configuration TAB
• Button Add
• Set parameters
• Set name
• Button OK
Software Timers lab 117
• Create Timer
• Button Add
• Button OK
Software Timers lab 118
• Type of hooks:
• Idle Hool
• Tick Hook
• Malloc Failed Hook
• Stack Overflow Hook
• Two options
• Option 1
• FreeRTOS check if the stack is in range
which was defined on task creation
• Option 2
• FreeRTOS use Option 1
• Secondary on the bottom of the stack is
known pattern
• If pattern is overwritten the stack is corrupted
Stack overflow hook 133