 Hello, my name is Artur and I would like to demonstrate to you a simple example how to create entity backend application on dual core STM42 WL55 devices and usage of hardware semaphores. Within this session I will create a dual core project for STM42 WL55 MCU using STM42 Qube IDE and I will demonstrate how to assign peripherals to both cores. In our case it would be use R2 and hardware semaphore. Then I will select configure and use hardware semaphores within the code. And using STM42 Qube IDE we will monitor peripherals within a debug session on two cores. As an illustration set terminal we will use built-in terminal within STM42 Qube IDE. What are the prerequisites for this session? I would use Nucleo WL55JC2 board, MicroUSB cable to connect this board to PC and PC with pre-installed the following software. STM42 Qube IDE I would use version 1.6.1 but this project can work as well on minimum 1.5.0. Then STM42 Qube library for STM42 WL devices in version 1.0.0 or more recent one. Hardware semaphore implementation within STM42 WL and its libraries. Let's start with some main points concerning hardware semaphores implementation in STM42 WL microcontrollers. This peripheral is existing within dual core and single core STM42 WL devices. It allows you to communicate between cores and within one core between different processes. You can find 16 hardware semaphores in STM42 WL devices. Each semaphore stores an information about the core and process which took it. Took means lock in fact. And if a semaphore is not taken its status registers are cleared. I've got two main registers for each semaphore. It is H-C-E-M-R-L-R-X and a similar R-X register. Semaphores can be used as I told already within single core or between cores to synchronize the actions and processes. Core can be locked when it is free. It is not taken by any processor core and its Proz-PRO-CID field is cleared within its configuration. After the reset semaphores are enabled by default and those are available for both cores but access to them can be separately disabled for each of the core. So it is up to the programmer to limit this access. There is a single interrupt for hardware semaphores which can be triggered by select semaphores once the semaphore is unlocked. Let's have a look on hardware semaphore registers. It is an extract from reference manual RM0453. So the main registers assigned to each semaphore are hardware semaphore register semaphore X and hardware semaphore read log register semaphore X. The first one where we have read write access is used in so called dual step locking mechanism where we need to put information about the Proz-ID. The core ID is filled automatically depending on the on the core which is calling the locking function and in the second test step this register is read back and the values are compared in case the core ID and Proz-ID are the same like previously written and the semaphore is locked for a given core and let's say set Proz-ID. The second register which is read only one it's a bit more tricky one. It is used for single step locking mechanism for hardware semaphores and it is used in such a way that we are calling the function by reading this content of this register and if this register is empty so in fact the semaphore is not locked for say any of the of the cores and processes. So log core ID and Proz-ID are zeroed. In this case the core ID is filled automatically by the core ID of the core which is calling this lock function. Proz-ID remains cleared and lock ID is set to one and as a result of this function the semaphore will be taken as well but in this case the Proz-ID would be set to zero. So this is the difference between those two registers. One more point on this slide and the core ID is set automatically so as we can see zero means the semaphore is not taken four means that it's taken by Cortex-M4 core and eight it means that is taken by Cortex-M0 plus core. Lock bit means that once it's cleared the semaphore is free and if it's set to one it means that semaphore is taken. Concerning Proz-ID this is completely dependent on the user it is 8-bit value which can be selected from zero up to ff hexadecimal and it fully depends on the user. It is worth to mention that it's possible to release all semaphores assigned to selected core at once. To do this we need to specify 16-bit value so-called key it is done within hardware semaphore key register. This register is common for both cores in fact and then once we access the hardware semaphore clear register with the same key value all of the semaphores locked by the core which is let's say accessing this clear register will be released automatically at once. Let's have a closer look on functions which are defined within hardware abstraction layer of STM32WL dedicated for hardware semaphores. All of them we will find within this hardware semaphore.c file. First two functions so hardware semaphore take and fast take are used to take or lock the semaphore. The first one is used if we would like to specify an additional argument called Proz-ID which is a 16-bit value. It is giving us an option to lock more than one semaphores by different processes so different tasks for example. If we are not planning to specify different tasks we can use just fast take function and in this case the Proz-ID will be filled with zero value and the only identity of the owner of the semaphore will be stored within the core ID of the caller of this function. We can check whether the semaphore is taken by using hardware semaphore is some taken function where we need to specify the semaphore ID. We've got two dedicated functions to release the semaphore. The first one needs two arguments semaphore ID and the process ID and the semaphore will be unlocked only if semaphore ID, process ID and core ID of the caller of this function will be equal to the values stored within a selected semaphore register otherwise the semaphore will be still locked. There is a function which allows us to release all semaphores assigned to the given core. To do this we need to specify the key value which needs to be specified later on within the key register which is common for both cores. This we can specify using function set clear key which we can see below. So once we call this release all function with the proper key value all of the semaphores which are assigned to the core ID equal to the caller of this function will be released automatically. We can as well read out the key which is stored within the key register using this get clear key value. It is possible as well to use the interrupts which would inform us about releasing the semaphores. To do this we need to use activate notification function which is specifying the semaphore mask. So it is we are selecting in fact the semaphores which would generate an interrupt once those semaphores would be released. We can as well do the opposite action so we can deactivate those notifications using the activate notification function. Semaphores can generate the interrupt. We can see this hardware semaphore IRQ handler which is common for all of the hardware semaphores and within this function there is after let's say the clearing of the flux operations which is done automatically by the hardware abstraction layer. There is a free callback function which can be used by us to our purposes. So in case of clearing or releasing some semaphore we can specify some special action. Here in the frame you can see the valid values for the arguments which are used within those functions. So semaphore ID it is a number from 0 to 31 within the valid range for the given micro. The process ID theoretically it is from 0 to 255 so it's 8 bit process ID then core ID is specified by hardware as following. So 4 is for Cortex-M4 and 8 is for Cortex-M0 plus. Key is 16 bit value from 0 to ff ff hexadecimal and set mask is as well 16 bit value from 0 to ff ff hexadecimal. On previous slide we have looked on the list of the functions which are available for hardware semaphores. Now let's have a look how we can take log the semaphore using those hardware abstraction layer functions. We've got two options. The first one could be used in the system where we've got more than one process so for example when we are working with operating system. This function is how hardware semaphore take and it needs in fact two arguments. The first argument is semaphore ID and the second argument is process ID. This process ID it's 8 bit value which is specified by the user and it allows us to use different log mechanisms depending on number of the of the threads of the tasks of the processes which are managed by the single core. If we would like to use the hardware semaphore without operating system we can use this hardware semaphore fast take function which is requiring only one argument which is the semaphore ID. In both functions the core ID is checked automatically by the system. The core ID is taken from the color of those functions and the proper values are stored within the registers for the given semaphores. Why we call those components two step and one step? When we are using hardware semaphore take function so the two step log we need to program the register for the given semaphore and then read it back and check whether what we just have written is the same what we read and in case the values are the same we are sure that the semaphore is taken as requested. In one step log procedure it is a bit more simple. We just read the semaphore which we would like to take and in case it was cleared so it was not taken the system automatically is feeling the core ID of the color of this function and the semaphore is automatically taken by the color of this hardware semaphore fast take. In this case the process ID will be set to zero so it's much more simple but it is not that flexible like hardware semaphore take. Thank you for watching this video.