STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf ·...

33
STM32 Ecosystem workshop T.O.M.A.S Team

Transcript of STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf ·...

Page 1: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

STM32 Ecosystem workshopT.O.M.A.S Team

Page 2: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

Now it is a right time for some practice – this time we will generate

the code for our L4_DAC_ADC application using Low Layer libraries.

We can work on L4_DAC_ADC.ioc file in STM32CubeMX.

2

Page 3: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

Goal of this partGain knowledge about the process of generation Low Layer Library concept

based code using STM32CubeMX

Practice Low Layer Library concept on generated project

Gain knowledge about differences between HAL and LL concepts.

4

Page 4: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

Low Layer Library code generation

Page 5: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

• Please open L4_DAC_ADC.ioc project in STM32CubeMX

• Remove USART2, SWO and EXTI13 peripherals.

• We will now test different options within code generation settings

6

Page 6: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

Generate code using Low Layer librariesSTM32CubeMX – Project settings window

Starting from STM32CubeMX v4.17.0 selection

between HAL and Low Layer Library driver can be

done independently for each peripheral selected in

STM32CubeMX during the configuration phase.

• To configure it, please select Project -> Project

Settings and select Advanced Settings tab

• In Driver Selector part, Driver column we can

select between HAL and LL for each of the

peripheral module

• We can disable code re-generation for selected

peripheral by “checking” the proper row within

Generated Function Calls

7

Page 7: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

• Change HAL to LL for each peripheral module

• Generate the code with added new features

• Perform further processing in SW4STM32 (L4_DAC_ADC project)

8

Page 8: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

Generate code using Low Layer librariesSW4STM32 – modified code structure

• Project generated by STM32CubeMX will contain either HAL or

LL driver files in Drivers->STM32L4xx_HAL_Driver path

(visible in Project Explorer)

• It is not possible to use HAL functions for the peripherals which

were initialized by Low Layer library functions as we do not have

proper peripheral handlers

• It is possible to use Low Layer functions on the peripheral

which was initialized by HAL functions, but we need to add manually proper LL header file (i.e. stm32l4xx_ll_gpio.h).

9

Page 9: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

1. Please comment all HAL related code

• between: /* USER CODE BEGIN 2 */ and /* USER CODE END 2 */ lines

• and between: /* USER CODE BEGIN 4 */ and /* USER CODE END 4*/ lines

as we do not have any HAL library nor EXTI/DMA/printf support in

the project now.

2. Additionally please comment all printf related code (inclusion of

stdio.h file) as we will work on first L4_DAC_ADC example

3. We need to add some activation code using Low Layer Library

functions for selected peripherals.

10

Page 10: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

L4_DAC_ADC projectdata buffers declaration

/* USER CODE BEGIN Includes */

#include "sine.h"

/* USER CODE END Includes */

/* USER CODE BEGIN PV */

/* Private variables ---------------------------------------------------------*/

#define ADCBUFSIZE 32

#define DACBUFSIZE 32

uint16_t adcbuf[ADCBUFSIZE];

/* USER CODE END PV */

11

• We can reuse the existing code from L4_DAC_ADC project

• It is necessary to define the source buffer for DAC (dacbuf[]) and destination buffer for ADC to store

the measured data (adcbuf[]). Size for both can be 32. We can reuse sine.h file content here.

Page 11: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

LL_L4_DAC_ADC projectDAC activation 12

LL_DAC_EnableDMAReq(DAC1, LL_DAC_CHANNEL_1);

LL_DAC_Enable(DAC1, LL_DAC_CHANNEL_1);

1

2

• STM32CubeMX is generating most of the configuration for DAC.

• The missing point is enabling DMA for selected channel of DAC using LL_DAC_EnableDMAReq()

function

• At the end we should enable selected channel on DAC channel using LL_DAC_Enable() function

• We would need to configure DMA transmission -> it will be described further in DMA section

1

2

Page 12: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

LL_L4_DAC_ADC projectADC activation - task 13

Most of the configuration steps are done by STM32CubeMX generated code. The missing points are

related to ADC activation and its start. We need to perform the following actions within our code:

1. After the reset ADC is in deep power down mode. It is necessary to disable this mode using

LL_ADC_DisableDeepPowerDown() function

2. Further we need to enable ADC internal voltage regulator using LL_ADC_EnableInternalRegulator() function

and wait for it stabilization (implement your own delay() function). It requires 20us for stabilization – the delay

should be added manually

3. Start calibration of ADC1 (for single ended conversions) using function LL_ADC_StartCalibration().

4. Add necessary 116 ADC clk delay after calibration start

5. Enable ADC1 using LL_ADC_Enable() function

6. Start regular conversion (ADC1 will start conversion after next HW trigger) using

LL_ADC_REG_StartConversion() function

We would need to configure DMA transmission -> it will be described further in DMA section

Page 13: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

LL_L4_DAC_ADC projectADC activation - solution 14

LL_ADC_DisableDeepPowerDown(ADC1);

LL_ADC_EnableInternalRegulator(ADC1);

//wait 20us for internal regulator stabilization

LL_ADC_StartCalibration(ADC1, LL_ADC_SINGLE_ENDED);

//necessary 116 ADC clk delay

LL_ADC_Enable(ADC1);

LL_ADC_REG_StartConversion(ADC1);

12

3

4

5

6

Page 14: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

LL_L4_DAC_ADC projectDMA activation 15

LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_3,(uint32_t)dacbuf,

LL_DAC_DMA_GetRegAddr(DAC1,LL_DAC_CHANNEL_1,LL_DAC_DMA_REG_DATA_12BITS_RIGHT_ALIGNED),

LL_DMA_DIRECTION_MEMORY_TO_PERIPH);

LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_3, DACBUFSIZE);

LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_3);

LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_1,

LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA),

(uint32_t)adcbuf, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);

LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, ADCBUFSIZE);

LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);

• STM32CubeMX is generating the basic configuration for DMA transfers used by DAC and ADC.

The missing points are: pointers to source and destination buffers and size of each transfer.

• To configure addresses of the buffers used by DMA we can sue the LL_DMA_ConfigAddresses() function

• To configure data length we can use the LL_DMA_SetDataLength() function

• At the end we should enable each DMA channel using LL_DMA_EnableChannel() function

DA

CA

DC

Page 15: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

LL_L4_DAC_ADC projectTIM2 activation

LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2);

LL_TIM_EnableCounter(TIM2);

16

• STM32CubeMX is generating most of the configuration for TIM2.

• The missing point is enabling selected output channel (Capture Compare channel2) using

LL_TIM_CC_EnableChannel() function

• At the end we should enable each DMA channel using LL_DMA_EnableChannel() function

1

2

1

2

Page 16: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

After all code modification, please:

• clean the project to remove all temporary files from HAL version

• It can be done by selection Project->Clean

• compile the project

• compare the code size for both configurations:

• HAL library ? kB

• LL library ? kB

17

Page 17: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

The next step could be adding the functionality of printf over SWO or

USART2 and processing interrupts on external signal and DMA

transfer complete (project from complementary debug tools) using

Low Layer concept.

18

Page 18: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

Adding SWO, EXTI13 and USART2STM32CubeMX – Pinout tab

1. Open L4_DAC_ADC.ioc project in STM32CubeMX

• Menu File Open Project

2. In STM32CubeMX, pinout tab enable SWO pin

• Select SYS Debug Trace Asynchronous Sw

3. Click left button on mouse over PC13 pin and select GPIO_EXTI13 mode

19

4. Select USART2 in asynchronous mode

• Select USART2->Mode: Asynchronous

Page 19: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

Configure USART2 and EXTI13STM32CubeMX – Configuration tab

• Configure USART2 parameters:

• 115200 bps / 8 bit data / 1 bit stop / no parity / no HW control

20

• Enable EXTI line[15:10] within NVIC

configuration

Page 20: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

• Generate the code with added new features using Low Layer libraries

• Perform further processing in SW4STM32 (L4_DAC_ADC project)

21

Page 21: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

Using SWO for printf in gcc

In main.c source file:

• include the stdio.h library to make printf

working

• define _write() function used to send data

over SWO using ITM_SendChar() function

• as ITM_SendChar() function is accepting

single character, we should send data

character by character in the loop.

• add some messages at the beginning of the

application

• compile and run the code

/* USER CODE BEGIN Includes */#include <stdio.h>/* USER CODE END Includes */

/* USER CODE BEGIN 4 */

int _write(int file, char *ptr, int len)

{

int DataIdx;

for(DataIdx=0; DataIdx<len; DataIdx++)

{

ITM_SendChar(*ptr++);

}

return len;

}

/* USER CODE END 4 */

22

printf("Application start.\n");

printf("Press User button to start new acquisition\n");

/* USER CODE END 2 */As we are not using HAL functions here (only

STDLIB and CMSIS ones), it is the same code

like in HAL version

Page 22: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

Using USART2 for printf in gcc

In main.c source file:

• include the stdio.h library to make

printf working

• define _write() function used to send

data over USART2

• add some messages at the beginning

of the application

/* USER CODE BEGIN Includes */#include <stdio.h>/* USER CODE END Includes */

/* USER CODE BEGIN 4 */

int _write(int file, char *ptr, int len)

{

int DataIdx;

for(DataIdx=0; DataIdx<len; DataIdx++)

{

while (!LL_USART_IsActiveFlag_TXE(USART2))

{

//we can put some timeout here

}

LL_USART_TransmitData8(USART2,*ptr++);

}

return len;

}

/* USER CODE END 4 */

23

printf("Application start.\n");

printf("Press User button to start new acquisition\n");

/* USER CODE END 2 */

Page 23: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

Sending ADC results over printfExternal interrupt handler (stm32l4xx_it.c file)

void EXTI15_10_IRQHandler(void)

{

/* USER CODE BEGIN EXTI15_10_IRQn 0 */

if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_13) != RESET)

{

LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_13); //clear the irq flag

GPIO_EXTI_Callback(LL_EXTI_LINE_13); //call the callback from main.c

}

/* USER CODE END EXTI15_10_IRQn 0 */

}

24

/* USER CODE BEGIN 0 */

#include "main.h"extern void GPIO_EXTI_Callback(uint16_t GPIO_Pin);/* USER CODE END 0 */

1. Include main.h file to have an access to Low Layer Library definitions

2. Declare external GPIO_EXTI_Callback() function

3. Check whether LL_EXTI_LINE_13 flag is set within EXTI15_10_IRQHandler() is set

4. Clear LL_EXTI_LINE_13

5. Call the proper callback (it will be defined in main.c file)

1

2

3

45

Page 24: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

Sending ADC results over printfExternal interrupt handler (main.c file)

25

/* USER CODE BEGIN 4 */

void GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

if(0==flag)

{

LL_TIM_CC_DisableChannel(TIM2,LL_TIM_CHANNEL_CH2);

printf("Acquisition stopped\n");

printf("Press button to START a new one\n");

flag=1;

}

else

{

printf("Acquisition started\n");

printf("Press button to STOP it\n");

flag=0;

LL_TIM_CC_EnableChannel(TIM2,LL_TIM_CHANNEL_CH2);

}

}

Additionally we should not start Timer2 at the

beginning (USER CODE 2 section, before

while(1) loop)

/* USER CODE BEGIN PV */

volatile uint8_t flag=1;

/* USER CODE BEGIN PFP */

void GPIO_EXTI_Callback(uint16_t GPIO_Pin);

1. Declare flag variable to store the state

2. Declare the GPIO_EXTI_Callback() function

which will be called from EXTI interrupt

handler on detection active edge on EXTI

line 13

3. Disable / enable channel2 of TIM2 within the

callback based on flag value

1

2

3

3

Page 25: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

Sending ADC results over printfDMA transfer complete interrupt handler (stm32l4xx_it.c file)

void DMA1_Channel1_IRQHandler(void)

{

/* USER CODE BEGIN DMA1_Channel1_IRQn 0 */

if(LL_DMA_IsActiveFlag_TC1(DMA1) == 1)

{

LL_DMA_ClearFlag_TC1(DMA1);

DMA_ADC_ConvCpltCallback();

}

/* USER CODE END DMA1_Channel1_IRQn 0 */

}

26

/* USER CODE BEGIN 0 */

#include "main.h"

extern void DMA_ADC_ConvCpltCallback(void);

1. Include main.h file to have an access to Low Layer Library definitions

2. Declare external DMA_ADC_ConvCpltCallback() function – we can use the same function structure

like in HAL library version

3. Check whether transfer complete flag is set within DMA1_Channel1_IRQHandler() is set

4. Clear transfer complete flag for channel 1 (TC1) on DMA1

5. Call the proper callback (it will be defined in main.c file)

12

3

45

Page 26: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

Sending ADC results over printfDMA transfer complete interrupt handler (main.c file)

27

void DMA_ADC_ConvCpltCallback()

{

printf("%d\n",adcbuf[0]);

}

/* USER CODE END 4 */

/* USER CODE BEGIN PFP */

void DMA_ADC_ConvCpltCallback(void);

LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);

//LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2);

1. Declare the DMA_ADC_ConvCpltCallback()

function which will be called from DMA

interrupt handler on transfer complete event

from channel1

2. Enable Transfer Complete interrupt for

DMA1 Channel1

3. Disable activation of Timer2, channel2 from

main() function

4. Put printf() within proper DMA_ADC

callback function

1

2

3

4

Page 27: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

After all code modification, please:

• clean the project to remove all temporary files from HAL version

• It can be done by selection Project->Clean

• compile the project

• compare the code size for both configurations:

• HAL library ? kB

• LL library ? kB

28

Page 28: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

29

Analyze the data from ADCdata sent over USART2

• Open serial terminal selecting COM port assigned to Virtual

COMP Port (VCP) implemented in STLink, using the

configuration:

• 115200pbs / 8 data bits / 1 STOP bit / NO parity / NO HW flow control

• Reset the board, now you should see “Application start”

message in terminal window

• Follow the instructions in the terminal window (User button is

the blue one on Nucleo board)

• Using copy&paste mechanism copy data to clipboard and

then paste them into the spread sheet application (i.e. Excel)

• Display the waveform

0

1000

2000

3000

4000

5000

1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31

Chart Title

Page 29: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

30• Open STLink Utility

• Connect to the board (Target Connect)

• Open SWO viewer window (ST-LINK Printf via SWO viewer)

• Update System clock to 80 000 000 and Stimulus to 0 (toolchain

settings)

• Start data catching Start button

• Grab the ADC data

• Using copy&paste mechanism copy data to clipboard and then paste

them into the spread sheet application (i.e. Excel)

• Display the waveform

0

1000

2000

3000

4000

5000

1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31

Chart Title

Hint: in case there is

nothing in trace window,

please check the version

of STLink firmware ->

see the next slide

Analyze the data from ADCdata sent over SWO

Page 30: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

31

SWO viewer in STLink UtilityNo data in trace window – upgrade of the driver

In case there is no data in trace window, it is highly probable that

the STLink software on Nucleo board is not up-to-date

• To update this software, please follow the below procedure:

• Select ST-LINK->Firmware update

• Press Device Connect button on “ST-Link Upgrade”

window

• After a while there will be information about firmware

version on STLink and the current one

• In case the current one has higher number, please upgrade

STLink by pressing Yes >>>> button

• After completion of the operation message window will

appear

• We can close “ST-Link Upgrade” window and continue

operations on upgraded board.

Page 31: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

What have we learnt?Gain knowledge about the process of generation Low Layer Library concept

based code using STM32CubeMX

Practice Low Layer Library concept on generated project

Gain knowledge about differences between HAL and LL concepts.

32

Page 32: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

Further reading 33

More information can be found in the following documents:

• UM1860 - Getting started with STM32CubeL4 for STM32L4 Series, available on the web:

http://www.st.com/resource/en/user_manual/dm00157440.pdf

• UM1884 - Description of STM32L4 HAL and Low-layer drivers, available on the web:

http://www.st.com/resource/en/user_manual/dm00173145.pdf

• Doxygen based html manual: STM32L486xx_User_Manual.chm, available within STM32L4xx

Cube library in the path:

\STM32Cube_FW_L4_V1.5.0\Drivers\STM32L4xx_HAL_Driver\

Page 33: STM32 Ecosystem workshop - Empaempa.com/.../13_Low-Layer-Library-code-generation_STM32CubeMX.pdf · Size for both can be 32. We can reuse sine.h file content here. LL_L4_DAC_ADC project

Enjoy!

www.st.com/mcu

/STM32 @ST_World st.com/e2e