STM32H5测评 | 开箱硬件测评分析与GPIO和PWM测试
本帖最后由 sunsili 于 2023-7-19 08:39 编辑STM32H5测评 | 开箱硬件测评分析与GPIO和PWM测试
来源:EEWORLD论坛网友 bigbat 版权归原作者所有
开箱硬件测评分析随着物联网的不断推进,网络通讯安全级别也在不断提高,普通的MCU在应对加解密和安全验证等应用时就有点力不从心,MCU的主要应用是小型的嵌入式设备,但安全应用又需要硬件具备一定性能,安全算法除了占用一定的MCU性能外还需要大量的代码和RAM空间,因而市场出现了很多“组合设计”,最常见的就是“MCU+高性能通讯模块”,在应用环境恶劣的场景下面临挑战,如在北方冬季无人值守的站点,因气温很低,会给通讯模块带来很多问题。基于arm Cortex-M33内核的高性能MCU — STM32H5,针对安全性和通讯性能增加了很多的性能。STM32H5系列提供了较大RAM(640K)和Flash(2M+),提供 4K Backup RAM 用来存储待机数据,主频更是提高到了250MHz。在安全方面,STM32H5 也是提供了M33内核的全部安全特性,TrustZone、内存保护、加密存储等特性。
NUCLEO-H563ZI 是主核为STM32H563ZI、144PIN脚的DEMO板。该板接口由原来的USB接口更新为 Type-C 接口,有以下外设:1、一个 RJ45 以太网口、PHY 使用的是 LAN8742,一个网络变压器;2、一个 VDD 触发按键作为输入,按键接了一个ESD ALC6V1的保护;3、一个LPUSART 接口,链接到板载的虚拟串口,与ST-LINK V3共用一个USB;4、一个全速 USB TYPE-C 接口,提供芯片的USB功能,及硬件保护和电源管理;5、LED和REST按键等外设。从板卡设计中可以看出ST公司加入了大量的接口保护设计参考。因板卡新的硬件特性,需要升级软件环境,STM32CubeMX需要升级到 v6.9 版,Java jre升级到17版;Keil 升级到 v6.0以上版本,同时下载STM32H5的包,ST-link V3的驱动也需要升级。点灯程序: NYUCLEO-H563ZI开发板的硬件引脚基本已经配置好了,只需配置没有扩展的引脚。程序点亮的是LED2。程序不是很复杂,代码很简单,但是M33内核需要的设置却很多。/* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */HAL_GPIO_TogglePin(LED2_YELLOW_GPIO_Port, LED2_YELLOW_Pin);HAL_Delay(500);/* USER CODE BEGIN 3 */}
GPIO和PWM测试为了呈现 STM32H563ZI 接近MPU的性能,本次测试使用freeRTOS系统进行PWM和GPIO的测试。首先,需要安装STM32Cube的STM32H5的freeRTOS系统模块,新建项目时选择“ACCESS TO EXAMPLE SELECTOR”项目,选择开发板NUCLEO-H563ZI,选择FreeRTOS_Semaphore_LowPower项目。项目默认打开了PWR管理,还有三个LED外设。我们的评测是使用一个低功耗定时器 LPTIM4 作为信号源来控制 GPIO 的输出。/* USER CODE BEGIN Header *//********************************************************************************* File Name : app_freertos.c* Description : Code for freertos applications******************************************************************************* @attention ** Copyright (c) 2023 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************//* USER CODE END Header *//* Includes ------------------------------------------------------------------*/#include "FreeRTOS.h"#include "task.h"#include "main.h"#include "cmsis_os2.h"/* Private includes ----------------------------------------------------------*//* USER CODE BEGIN Includes *//* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*//* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*//* USER CODE BEGIN PD */#define DEFAULT_TIMEOUT (1000)/* USER CODE END PD *//* Private macro -------------------------------------------------------------*//* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN Variables */extern LPTIM_HandleTypeDef hlptim4;/* USER CODE END Variables *//* Definitions for MainThread */osThreadId_t MainThreadHandle;const osThreadAttr_t MainThread_attributes = {.name = "MainThread",.priority = (osPriority_t) osPriorityNormal,.stack_size = 256 * 4};/* Definitions for BinarySemaphore */osSemaphoreId_t BinarySemaphoreHandle;const osSemaphoreAttr_t BinarySemaphore_attributes = {.name = "BinarySemaphore"};/* Private function prototypes -----------------------------------------------*//* USER CODE BEGIN FunctionPrototypes */void SystemClock_Config(void);/* USER CODE END FunctionPrototypes */void MainThread_Entry(void *argument);void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) *//* USER CODE BEGIN PREPOSTSLEEP */void PreSleepProcessing(uint32_t ulExpectedIdleTime){/* This is needed to prevent TIM6 from triggering an interrupt, * which could prevent the CPU from entering STOP mode */HAL_SuspendTick();/* Start low power timer */HAL_LPTIM_TimeOut_Start_IT(&hlptim4, DEFAULT_TIMEOUT);/* Enter STOP mode */HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);}void PostSleepProcessing(uint32_t ulExpectedIdleTime){/* Restore Clock settings */SystemClock_Config();/* Resume HAL timebase */HAL_ResumeTick();}/* USER CODE END PREPOSTSLEEP *//*** @brief FreeRTOS initialization* @paramNone* @retval None*/void MX_FREERTOS_Init(void) {/* USER CODE BEGIN Init *//* USER CODE END Init *//* USER CODE BEGIN RTOS_MUTEX *//* add mutexes, ... *//* USER CODE END RTOS_MUTEX *//* creation of BinarySemaphore */BinarySemaphoreHandle = osSemaphoreNew(1, 1, &BinarySemaphore_attributes);/* USER CODE BEGIN RTOS_SEMAPHORES *//* add semaphores, ... *//* USER CODE END RTOS_SEMAPHORES *//* USER CODE BEGIN RTOS_TIMERS *//* start timers, add new ones, ... *//* USER CODE END RTOS_TIMERS *//* USER CODE BEGIN RTOS_QUEUES *//* add queues, ... *//* USER CODE END RTOS_QUEUES *//* creation of MainThread */MainThreadHandle = osThreadNew(MainThread_Entry, NULL, &MainThread_attributes);/* USER CODE BEGIN RTOS_THREADS *//* add threads, ... *//* USER CODE END RTOS_THREADS *//* USER CODE BEGIN RTOS_EVENTS *//* add events, ... *//* USER CODE END RTOS_EVENTS */}/* USER CODE BEGIN Header_MainThread_Entry *//*** @brief Function implementing the MainThread thread.* @param argument: Not used* @retval None*//* USER CODE END Header_MainThread_Entry */void MainThread_Entry(void *argument){/* USER CODE BEGIN MainThread *//* Infinite loop */for(;;osSemaphoreAcquire(BinarySemaphoreHandle, osWaitForever)){ HAL_GPIO_TogglePin(LED1_GREEN_GPIO_Port, LED1_GREEN_Pin);}/* USER CODE END MainThread */}/* Private application code --------------------------------------------------*//* USER CODE BEGIN Application */void HAL_LPTIM_CompareMatchCallback(LPTIM_HandleTypeDef *hlptim){if(hlptim->Instance == LPTIM4){ osSemaphoreRelease(BinarySemaphoreHandle); HAL_LPTIM_TimeOut_Stop_IT(&hlptim4);}}/* USER CODE END Application */
程序中首先声明了一个信号量 BinarySemaphoreHandle,作为 GPIO 的控制开关,然后在中断回调 HAL_LPTIM_CompareMatchCallback 中生成这个信号量。//信号量osSemaphoreId_t BinarySemaphoreHandle;//回调函数/* Private application code --------------------------------------------------*//* USER CODE BEGIN Application */void HAL_LPTIM_CompareMatchCallback(LPTIM_HandleTypeDef *hlptim){if(hlptim->Instance == LPTIM4){ osSemaphoreRelease(BinarySemaphoreHandle); HAL_LPTIM_TimeOut_Stop_IT(&hlptim4);}}
信号生成后,等待系统自己调度,这时需要将LPTIM4中断关掉。HAL_LPTIM_TimeOut_Stop_IT(&hlptim4);/* USER CODE END Header_MainThread_Entry */void MainThread_Entry(void *argument){/* USER CODE BEGIN MainThread *//* Infinite loop */for(;;osSemaphoreAcquire(BinarySemaphoreHandle, osWaitForever)){ HAL_GPIO_TogglePin(LED2_YELLOW_GPIO_Port, LED2_YELLOW_Pin);}/* USER CODE END MainThread */}
信号到达后翻转GPIO输出,系统运行后LED2,进入不停的闪烁。这里我把LED1改成了LED2,PWM的测试选择了 FreeRTOS_Mutex 例程,主要是因为 PWM 的输出需要更加严格的同步和控制。低功耗模式不适合该应用。PWM的输出设置需要理清程序的同步逻辑。程序首先定义了两个线程Thread1和Thread2,一个Mutex锁信号MutexHandle,通过这个信号进行 UART 资源的保护运行。osThreadId_t Thread1Handle;const osThreadAttr_t Thread1_attributes = {.name = "Thread1",.priority = (osPriority_t) osPriorityNormal,.stack_size = 256 * 4};/* Definitions for Thread2 */osThreadId_t Thread2Handle;const osThreadAttr_t Thread2_attributes = {.name = "Thread2",.priority = (osPriority_t) osPriorityNormal,.stack_size = 256 * 4};/* Definitions for Mutex */osMutexId_t MutexHandle;const osMutexAttr_t Mutex_attributes = {.name = "Mutex"};
首先两个线程在运行前半段使用信号锁进行共用资源 uart 的运行,后面进行运行。/* USER CODE BEGIN Header_Thread1_Entry *//*** @brief Function implementing the Thread1 thread.* @param argument: Not used* @retval None*//* USER CODE END Header_Thread1_Entry */void Thread1_Entry(void *argument){/* USER CODE BEGIN Thread1 */uint16_t i;/* Infinite loop */for(i = 0; i < 10; ++i){#if EXAMPLE_USES_MUTEXosMutexAcquire(MutexHandle, osWaitForever);printf ("Thread1: Mutex Acquired!\n");#endif
printf("Thread1 : This is message number %u\n", i+1);
#if EXAMPLE_USES_MUTEXprintf ("Thread1: Mutex Released!\n");osMutexRelease(MutexHandle);#endif HAL_GPIO_TogglePin(LED1_GREEN_GPIO_Port, LED1_GREEN_Pin); osDelay(200);}
while(1){ HAL_GPIO_TogglePin(LED1_GREEN_GPIO_Port, LED1_GREEN_Pin); osDelay(1000);}/* USER CODE END Thread1 */}
/* USER CODE BEGIN Header_Thread2_Entry *//*** @brief Function implementing the Thread2 thread.* @param argument: Not used* @retval None*//* USER CODE END Header_Thread2_Entry */void Thread2_Entry(void *argument){/* USER CODE BEGIN Thread2 */uint16_t i;
/* Infinite loop */for(i = 0; i < 10; ++i){#if EXAMPLE_USES_MUTEX osMutexAcquire(MutexHandle, osWaitForever); printf ("Thread2: Mutex Acquired!\n"); #endif
printf("Thread2 : This is message number %u\n", i+1);#if EXAMPLE_USES_MUTEX printf ("Thread2: Mutex Released!\n"); osMutexRelease(MutexHandle); #endif HAL_GPIO_TogglePin(LED2_YELLOW_GPIO_Port, LED2_YELLOW_Pin); osDelay(200);}
while(1){ HAL_GPIO_TogglePin(LED2_YELLOW_GPIO_Port, LED2_YELLOW_Pin); osDelay(1000);} /* USER CODE END Thread2 */}
/* Private application code --------------------------------------------------*//* USER CODE BEGIN Application *//* USER CODE END Application */
进程先获取信号锁,在进行打印输出,输出完成后再解锁,这样可以保证三段打印都是同一个线程的输出。可以看出每次的输出都是一个线程的信息。下面进行PWM的改造测试PWM的设置如图,使用LED1作为PWM的输出,所以设置PB0作为TIM3的CH3通道,PWM输出,脉宽比为50%,所以计数为2048,PLUSE VALUE=1024。设置好以后将程序进行改造,另起一个项目通过CUBE生成初始化代码,然后改造项目。/* USER CODE BEGIN Header_Thread1_Entry *//*** @brief Function implementing the Thread1 thread.* @param argument: Not used* @retval None*//* USER CODE END Header_Thread1_Entry */void Thread1_Entry(void *argument){
osMutexAcquire(MutexHandle, osWaitForever);printf ("Thread1: Mutex Acquired!\n");printf("Thread1 : PWM starter\n ");printf ("Thread1: Mutex Released!\n");osMutexRelease(MutexHandle); HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_3);while(1){ osDelay(1);}/* USER CODE END Thread1 */}
项目启动后。可以看到LED1开始开始工作。
页:
[1]