Skip to main content
cbarb2747
Associate III
February 16, 2026
Question

SPI Or UART On STM32H7S78-DK

  • February 16, 2026
  • 2 replies
  • 264 views

I have an STM32H7S78-DK and I have used TouchGFX to create a GUI just fine. I am currently trying to use the fanout or the Arduino headers to communicate through SPI or UART to another board.  The first thing I tried was using the SPI through the fanout board as it's soldered for the SPI4 by default with the fanout board.  I used the female headers on the fanout board that corresponded with MOSI, MISO, etc for the SPI.  I configured SPI4 in STMCubeMX and generated the code in STMCubeIDE.  I just tried to send an array with Hello in the array in the form of hex values.  However, I saw nothing coming out of the pins when I hooked it up to a logic analyzer. I then thought maybe I was using the wrong header and soldered some male pins next to the female pins which said CN12 which corresponded to what it said in the fanout boards documentation. I thought maybe the microbus female headers were not the right ones to use.  Generated all the code and tried again and nothing.  Then I though I'd try to use UART7 with the Arduino pins, but I still get nothing.  Am I doing something wrong?  I'd ideally like to use the STMOD+ connector with SPI.  I can't figure out why it's not working. I used a STM32L476RG as a spi slave for a sanity check and I can send data actually to that board from a raspberry pi over SPI.  So I am thinking with the STM32H7S78-DK it is just something I'm not enabling correctly, but it should be pretty straight forward if you are using STMCubeMX.  So maybe it's a jumper or something. Any help would be greatly appreciated to get me on the right track. Thanks.

2 replies

MGogr.1
Senior
February 16, 2026

If your hardware is proper then, Some code snippet would be useful.

cbarb2747
cbarb2747Author
Associate III
February 17, 2026

Here is the main.c with just a simple hello getting sent every two seconds.

 

/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * @file : main.c
 * @brief : Main program body
 ******************************************************************************
 * @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 "main.h"
#include "FreeRTOS.h"
#include "cmsis_os2.h"
#include "app_touchgfx.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 */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

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

CRC_HandleTypeDef hcrc;

DMA2D_HandleTypeDef hdma2d;

GPU2D_HandleTypeDef hgpu2d;

I2C_HandleTypeDef hi2c1;

JPEG_HandleTypeDef hjpeg;
DMA_HandleTypeDef handle_HPDMA1_Channel1;
DMA_HandleTypeDef handle_HPDMA1_Channel0;

LTDC_HandleTypeDef hltdc;

SPI_HandleTypeDef hspi4;

/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
 .name = "defaultTask",
 .stack_size = 128 * 4,
 .priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for TouchGFXTask */
osThreadId_t TouchGFXTaskHandle;
const osThreadAttr_t TouchGFXTask_attributes = {
 .name = "TouchGFXTask",
 .stack_size = 4096 * 4,
 .priority = (osPriority_t) osPriorityNormal,
};
/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
static void MPU_Config(void);
static void MX_GPIO_Init(void);
static void MX_HPDMA1_Init(void);
static void MX_LTDC_Init(void);
static void MX_CRC_Init(void);
static void MX_DMA2D_Init(void);
static void MX_JPEG_Init(void);
static void MX_FLASH_Init(void);
static void MX_I2C1_Init(void);
static void MX_GPU2D_Init(void);
static void MX_ICACHE_GPU2D_Init(void);
static void MX_SPI4_Init(void);
void StartDefaultTask(void *argument);
extern void TouchGFX_Task(void *argument);

/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t tx_data[6] = {0x48, 0x65, 0x6c, 0x6c, 0x6f};
/* USER CODE END 0 */

/**
 * @brief The application entry point.
 * @retval int
 */
int main(void)
{

 /* USER CODE BEGIN 1 */

 /* USER CODE END 1 */

 /* MPU Configuration--------------------------------------------------------*/
 MPU_Config();

 /* Enable the CPU Cache */

 /* Enable I-Cache---------------------------------------------------------*/
 SCB_EnableICache();

 /* Enable D-Cache---------------------------------------------------------*/
 SCB_EnableDCache();

 /* MCU Configuration--------------------------------------------------------*/

 /* Update SystemCoreClock variable according to RCC registers values. */
 SystemCoreClockUpdate();

 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();

 /* USER CODE BEGIN Init */

 /* USER CODE END Init */

 /* USER CODE BEGIN SysInit */

 /* USER CODE END SysInit */

 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_HPDMA1_Init();
 MX_LTDC_Init();
 MX_CRC_Init();
 MX_DMA2D_Init();
 MX_JPEG_Init();
 MX_FLASH_Init();
 MX_I2C1_Init();
 MX_GPU2D_Init();
 MX_ICACHE_GPU2D_Init();
 MX_SPI4_Init();
 MX_TouchGFX_Init();
 /* Call PreOsInit function */
 MX_TouchGFX_PreOSInit();
 /* USER CODE BEGIN 2 */

 /* USER CODE END 2 */

 /* Init scheduler */
 osKernelInitialize();

 /* USER CODE BEGIN RTOS_MUTEX */
 /* add mutexes, ... */
 /* USER CODE END RTOS_MUTEX */

 /* 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 */

 /* Create the thread(s) */
 /* creation of defaultTask */
 defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

 /* creation of TouchGFXTask */
 TouchGFXTaskHandle = osThreadNew(TouchGFX_Task, NULL, &TouchGFXTask_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 */

 /* Start scheduler */
 osKernelStart();

 /* We should never get here as control is now taken by the scheduler */

 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 HAL_GPIO_WritePin(SPI4_CS_GPIO_Port, SPI4_CS_Pin, GPIO_PIN_SET);

 while (1)
 {
	HAL_GPIO_WritePin(SPI4_CS_GPIO_Port, SPI4_CS_Pin, GPIO_PIN_RESET);
	HAL_SPI_Transmit(&hspi4, tx_data, sizeof(tx_data), 1000);
	HAL_GPIO_WritePin(SPI4_CS_GPIO_Port, SPI4_CS_Pin, GPIO_PIN_SET);
	HAL_Delay(2000);
 /* USER CODE END WHILE */

 /* USER CODE BEGIN 3 */
 }
 /* USER CODE END 3 */
}

/**
 * @brief CRC Initialization Function
 * @PAram None
 * @retval None
 */
static void MX_CRC_Init(void)
{

 /* USER CODE BEGIN CRC_Init 0 */

 /* USER CODE END CRC_Init 0 */

 /* USER CODE BEGIN CRC_Init 1 */

 /* USER CODE END CRC_Init 1 */
 hcrc.Instance = CRC;
 hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE;
 hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE;
 hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
 hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
 hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
 if (HAL_CRC_Init(&hcrc) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN CRC_Init 2 */

 /* USER CODE END CRC_Init 2 */

}

/**
 * @brief DMA2D Initialization Function
 * @PAram None
 * @retval None
 */
static void MX_DMA2D_Init(void)
{

 /* USER CODE BEGIN DMA2D_Init 0 */

 /* USER CODE END DMA2D_Init 0 */

 /* USER CODE BEGIN DMA2D_Init 1 */

 /* USER CODE END DMA2D_Init 1 */
 hdma2d.Instance = DMA2D;
 hdma2d.Init.Mode = DMA2D_R2M;
 hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB888;
 hdma2d.Init.OutputOffset = 0;
 if (HAL_DMA2D_Init(&hdma2d) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN DMA2D_Init 2 */

 /* USER CODE END DMA2D_Init 2 */

}

/**
 * @brief FLASH Initialization Function
 * @PAram None
 * @retval None
 */
static void MX_FLASH_Init(void)
{

 /* USER CODE BEGIN FLASH_Init 0 */

 /* USER CODE END FLASH_Init 0 */

 FLASH_OBProgramInitTypeDef pOBInit = {0};

 /* USER CODE BEGIN FLASH_Init 1 */

 /* USER CODE END FLASH_Init 1 */
 HAL_FLASHEx_OBGetConfig(&pOBInit);
 if ((pOBInit.USERConfig1 & OB_IWDG_SW) != OB_IWDG_SW||
(pOBInit.USERConfig1 & OB_XSPI1_HSLV_ENABLE) != OB_XSPI1_HSLV_ENABLE||
(pOBInit.USERConfig1 & OB_XSPI2_HSLV_ENABLE) != OB_XSPI2_HSLV_ENABLE||
(pOBInit.USERConfig2 & OB_I2C_NI3C_I2C) != OB_I2C_NI3C_I2C)
 {
 if (HAL_FLASH_Unlock() != HAL_OK)
 {
 Error_Handler();
 }
 if (HAL_FLASH_OB_Unlock() != HAL_OK)
 {
 Error_Handler();
 }
 pOBInit.OptionType = OPTIONBYTE_USER;
 pOBInit.USERType = OB_USER_IWDG_SW|OB_USER_XSPI1_HSLV
 |OB_USER_XSPI2_HSLV|OB_USER_I2C_NI3C;
 pOBInit.USERConfig1 = OB_IWDG_SW|OB_XSPI1_HSLV_ENABLE
 |OB_XSPI2_HSLV_ENABLE;
 pOBInit.USERConfig2 = OB_I2C_NI3C_I2C;
 if (HAL_FLASHEx_OBProgram(&pOBInit) != HAL_OK)
 {
 Error_Handler();
 }
 if (HAL_FLASH_OB_Lock() != HAL_OK)
 {
 Error_Handler();
 }
 if (HAL_FLASH_Lock() != HAL_OK)
 {
 Error_Handler();
 }
 }
 /* USER CODE BEGIN FLASH_Init 2 */

 /* USER CODE END FLASH_Init 2 */

}

/**
 * @brief GPU2D Initialization Function
 * @PAram None
 * @retval None
 */
static void MX_GPU2D_Init(void)
{

 /* USER CODE BEGIN GPU2D_Init 0 */

 /* USER CODE END GPU2D_Init 0 */

 /* USER CODE BEGIN GPU2D_Init 1 */

 /* USER CODE END GPU2D_Init 1 */
 hgpu2d.Instance = GPU2D;
 if (HAL_GPU2D_Init(&hgpu2d) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN GPU2D_Init 2 */

 /* USER CODE END GPU2D_Init 2 */

}

/**
 * @brief HPDMA1 Initialization Function
 * @PAram None
 * @retval None
 */
static void MX_HPDMA1_Init(void)
{

 /* USER CODE BEGIN HPDMA1_Init 0 */

 /* USER CODE END HPDMA1_Init 0 */

 /* Peripheral clock enable */
 __HAL_RCC_HPDMA1_CLK_ENABLE();

 /* HPDMA1 interrupt Init */
 HAL_NVIC_SetPriority(HPDMA1_Channel0_IRQn, 5, 0);
 HAL_NVIC_EnableIRQ(HPDMA1_Channel0_IRQn);
 HAL_NVIC_SetPriority(HPDMA1_Channel1_IRQn, 5, 0);
 HAL_NVIC_EnableIRQ(HPDMA1_Channel1_IRQn);

 /* USER CODE BEGIN HPDMA1_Init 1 */

 /* USER CODE END HPDMA1_Init 1 */
 /* USER CODE BEGIN HPDMA1_Init 2 */

 /* USER CODE END HPDMA1_Init 2 */

}

/**
 * @brief I2C1 Initialization Function
 * @PAram None
 * @retval None
 */
static void MX_I2C1_Init(void)
{

 /* USER CODE BEGIN I2C1_Init 0 */

 /* USER CODE END I2C1_Init 0 */

 /* USER CODE BEGIN I2C1_Init 1 */

 /* USER CODE END I2C1_Init 1 */
 hi2c1.Instance = I2C1;
 hi2c1.Init.Timing = 0x00E063FF;
 hi2c1.Init.OwnAddress1 = 0;
 hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
 hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
 hi2c1.Init.OwnAddress2 = 0;
 hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
 hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
 hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
 if (HAL_I2C_Init(&hi2c1) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure Analogue filter
 */
 if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure Digital filter
 */
 if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN I2C1_Init 2 */

 /* USER CODE END I2C1_Init 2 */

}

/**
 * @brief ICACHE_GPU2D Initialization Function
 * @PAram None
 * @retval None
 */
static void MX_ICACHE_GPU2D_Init(void)
{

 /* USER CODE BEGIN ICACHE_GPU2D_Init 0 */

 /* USER CODE END ICACHE_GPU2D_Init 0 */

 /* USER CODE BEGIN ICACHE_GPU2D_Init 1 */

 /* USER CODE END ICACHE_GPU2D_Init 1 */

 /** Enable instruction cache (default 2-ways set associative cache)
 */
 if (HAL_ICACHE_Enable() != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN ICACHE_GPU2D_Init 2 */

 /* USER CODE END ICACHE_GPU2D_Init 2 */

}

/**
 * @brief JPEG Initialization Function
 * @PAram None
 * @retval None
 */
static void MX_JPEG_Init(void)
{

 /* USER CODE BEGIN JPEG_Init 0 */

 /* USER CODE END JPEG_Init 0 */

 /* USER CODE BEGIN JPEG_Init 1 */

 /* USER CODE END JPEG_Init 1 */
 hjpeg.Instance = JPEG;
 if (HAL_JPEG_Init(&hjpeg) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN JPEG_Init 2 */

 /* USER CODE END JPEG_Init 2 */

}

/**
 * @brief LTDC Initialization Function
 * @PAram None
 * @retval None
 */
static void MX_LTDC_Init(void)
{

 /* USER CODE BEGIN LTDC_Init 0 */

 /* USER CODE END LTDC_Init 0 */

 LTDC_LayerCfgTypeDef pLayerCfg = {0};

 /* USER CODE BEGIN LTDC_Init 1 */

 /* USER CODE END LTDC_Init 1 */
 hltdc.Instance = LTDC;
 hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL;
 hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL;
 hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL;
 hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
 hltdc.Init.HorizontalSync = 4;
 hltdc.Init.VerticalSync = 4;
 hltdc.Init.AccumulatedHBP = 12;
 hltdc.Init.AccumulatedVBP = 12;
 hltdc.Init.AccumulatedActiveW = 812;
 hltdc.Init.AccumulatedActiveH = 492;
 hltdc.Init.TotalWidth = 820;
 hltdc.Init.TotalHeigh = 506;
 hltdc.Init.Backcolor.Blue = 0;
 hltdc.Init.Backcolor.Green = 0;
 hltdc.Init.Backcolor.Red = 0;
 if (HAL_LTDC_Init(&hltdc) != HAL_OK)
 {
 Error_Handler();
 }
 pLayerCfg.WindowX0 = 0;
 pLayerCfg.WindowX1 = 800;
 pLayerCfg.WindowY0 = 0;
 pLayerCfg.WindowY1 = 480;
 pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;
 pLayerCfg.Alpha = 255;
 pLayerCfg.Alpha0 = 0;
 pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;
 pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;
 pLayerCfg.FBStartAdress = 0;
 pLayerCfg.ImageWidth = 800;
 pLayerCfg.ImageHeight = 480;
 pLayerCfg.Backcolor.Blue = 0;
 pLayerCfg.Backcolor.Green = 0;
 pLayerCfg.Backcolor.Red = 0;
 if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN LTDC_Init 2 */

 /* USER CODE END LTDC_Init 2 */

}

/**
 * @brief SPI4 Initialization Function
 * @PAram None
 * @retval None
 */
static void MX_SPI4_Init(void)
{

 /* USER CODE BEGIN SPI4_Init 0 */

 /* USER CODE END SPI4_Init 0 */

 /* USER CODE BEGIN SPI4_Init 1 */

 /* USER CODE END SPI4_Init 1 */
 /* SPI4 parameter configuration*/
 hspi4.Instance = SPI4;
 hspi4.Init.Mode = SPI_MODE_MASTER;
 hspi4.Init.Direction = SPI_DIRECTION_2LINES;
 hspi4.Init.DataSize = SPI_DATASIZE_8BIT;
 hspi4.Init.CLKPolarity = SPI_POLARITY_LOW;
 hspi4.Init.CLKPhase = SPI_PHASE_1EDGE;
 hspi4.Init.NSS = SPI_NSS_SOFT;
 hspi4.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
 hspi4.Init.FirstBit = SPI_FIRSTBIT_MSB;
 hspi4.Init.TIMode = SPI_TIMODE_DISABLE;
 hspi4.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
 hspi4.Init.CRCPolynomial = 0x7;
 hspi4.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
 hspi4.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
 hspi4.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
 hspi4.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
 hspi4.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
 hspi4.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
 hspi4.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
 hspi4.Init.IOSwap = SPI_IO_SWAP_DISABLE;
 hspi4.Init.ReadyMasterManagement = SPI_RDY_MASTER_MANAGEMENT_INTERNALLY;
 hspi4.Init.ReadyPolarity = SPI_RDY_POLARITY_HIGH;
 if (HAL_SPI_Init(&hspi4) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN SPI4_Init 2 */

 /* USER CODE END SPI4_Init 2 */

}

/**
 * @brief GPIO Initialization Function
 * @PAram None
 * @retval None
 */
static void MX_GPIO_Init(void)
{
 GPIO_InitTypeDef GPIO_InitStruct = {0};
 /* USER CODE BEGIN MX_GPIO_Init_1 */
 /* USER CODE END MX_GPIO_Init_1 */

 /* GPIO Ports Clock Enable */
 __HAL_RCC_GPIOF_CLK_ENABLE();
 __HAL_RCC_GPIOE_CLK_ENABLE();
 __HAL_RCC_GPIOG_CLK_ENABLE();
 __HAL_RCC_GPIOB_CLK_ENABLE();
 __HAL_RCC_GPIOA_CLK_ENABLE();

 /*Configure GPIO pin Output Level */
 HAL_GPIO_WritePin(GPIOF, FRAME_RATE_Pin|RENDER_TIME_Pin|MCU_ACTIVE_Pin|VSYNC_FREQ_Pin, GPIO_PIN_RESET);

 /*Configure GPIO pin Output Level */
 HAL_GPIO_WritePin(LCD_EN_GPIO_Port, LCD_EN_Pin, GPIO_PIN_SET);

 /*Configure GPIO pin Output Level */
 HAL_GPIO_WritePin(LCD_BL_CTRL_GPIO_Port, LCD_BL_CTRL_Pin, GPIO_PIN_SET);

 /*Configure GPIO pin Output Level */
 HAL_GPIO_WritePin(SPI4_CS_GPIO_Port, SPI4_CS_Pin, GPIO_PIN_RESET);

 /*Configure GPIO pins : FRAME_RATE_Pin RENDER_TIME_Pin VSYNC_FREQ_Pin */
 GPIO_InitStruct.Pin = FRAME_RATE_Pin|RENDER_TIME_Pin|VSYNC_FREQ_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
 HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

 /*Configure GPIO pin : MCU_ACTIVE_Pin */
 GPIO_InitStruct.Pin = MCU_ACTIVE_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(MCU_ACTIVE_GPIO_Port, &GPIO_InitStruct);

 /*Configure GPIO pins : LCD_EN_Pin SPI4_CS_Pin */
 GPIO_InitStruct.Pin = LCD_EN_Pin|SPI4_CS_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

 /*Configure GPIO pin : TP_IRQ_Pin */
 GPIO_InitStruct.Pin = TP_IRQ_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(TP_IRQ_GPIO_Port, &GPIO_InitStruct);

 /*Configure GPIO pin : LCD_BL_CTRL_Pin */
 GPIO_InitStruct.Pin = LCD_BL_CTRL_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(LCD_BL_CTRL_GPIO_Port, &GPIO_InitStruct);

 /* EXTI interrupt init*/
 HAL_NVIC_SetPriority(TP_IRQ_EXTI_IRQn, 5, 0);
 HAL_NVIC_EnableIRQ(TP_IRQ_EXTI_IRQn);

 /* USER CODE BEGIN MX_GPIO_Init_2 */
 /* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/* USER CODE BEGIN Header_StartDefaultTask */
/**
 * @brief Function implementing the defaultTask thread.
 * @PAram argument: Not used
 * @retval None
 */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
 /* USER CODE BEGIN 5 */
 /* Infinite loop */
 for(;;)
 {
 osDelay(1);
 }
 /* USER CODE END 5 */
}

 /* MPU Configuration */

static void MPU_Config(void)
{
 MPU_Region_InitTypeDef MPU_InitStruct = {0};

 /* Disables the MPU */
 HAL_MPU_Disable();

 /* Disables all MPU regions */
 for(uint8_t i=0; i<__MPU_REGIONCOUNT; i++)
 {
 HAL_MPU_DisableRegion(i);
 }

 /** Initializes and configures the Region and the memory to be protected
 */
 MPU_InitStruct.Enable = MPU_REGION_ENABLE;
 MPU_InitStruct.Number = MPU_REGION_NUMBER0;
 MPU_InitStruct.BaseAddress = 0x0;
 MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
 MPU_InitStruct.SubRegionDisable = 0x87;
 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
 MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
 MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
 MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
 MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
 MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 /** Initializes and configures the Region and the memory to be protected
 */
 MPU_InitStruct.Number = MPU_REGION_NUMBER1;
 MPU_InitStruct.BaseAddress = 0x70000000;
 MPU_InitStruct.Size = MPU_REGION_SIZE_128MB;
 MPU_InitStruct.SubRegionDisable = 0x0;
 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
 MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
 MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
 MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
 MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;

 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 /** Initializes and configures the Region and the memory to be protected
 */
 MPU_InitStruct.Number = MPU_REGION_NUMBER2;
 MPU_InitStruct.Size = MPU_REGION_SIZE_2MB;
 MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 /** Initializes and configures the Region and the memory to be protected
 */
 MPU_InitStruct.Number = MPU_REGION_NUMBER3;
 MPU_InitStruct.BaseAddress = 0x90000000;
 MPU_InitStruct.Size = MPU_REGION_SIZE_32MB;
 MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
 MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
 MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 /** Initializes and configures the Region and the memory to be protected
 */
 MPU_InitStruct.Number = MPU_REGION_NUMBER4;
 MPU_InitStruct.BaseAddress = 0x20000000;
 MPU_InitStruct.Size = MPU_REGION_SIZE_64KB;

 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 /** Initializes and configures the Region and the memory to be protected
 */
 MPU_InitStruct.Number = MPU_REGION_NUMBER5;
 MPU_InitStruct.BaseAddress = 0x24000000;
 MPU_InitStruct.Size = MPU_REGION_SIZE_512KB;
 MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
 MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
 MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;

 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 /** Initializes and configures the Region and the memory to be protected
 */
 MPU_InitStruct.Number = MPU_REGION_NUMBER6;
 MPU_InitStruct.BaseAddress = 0x2406c000;
 MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
 MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;

 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 /** Initializes and configures the Region and the memory to be protected
 */
 MPU_InitStruct.Number = MPU_REGION_NUMBER7;
 MPU_InitStruct.BaseAddress = 0x24070000;
 MPU_InitStruct.Size = MPU_REGION_SIZE_8KB;

 HAL_MPU_ConfigRegion(&MPU_InitStruct);
 /* Enables the MPU */
 HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

}

/**
 * @brief Period elapsed callback in non blocking mode
 * @note This function is called when TIM6 interrupt took place, inside
 * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
 * a global variable "uwTick" used as application time base.
 * @PAram htim TIM handle
 * @retval None
 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
 /* USER CODE BEGIN Callback 0 */

 /* USER CODE END Callback 0 */
 if (htim->Instance == TIM6) {
 HAL_IncTick();
 }
 /* USER CODE BEGIN Callback 1 */

 /* USER CODE END Callback 1 */
}

/**
 * @brief This function is executed in case of error occurrence.
 * @retval None
 */
void Error_Handler(void)
{
 /* USER CODE BEGIN Error_Handler_Debug */
 /* User can add his own implementation to report the HAL error return state */
 __disable_irq();
 while (1)
 {
 }
 /* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
 * @brief Reports the name of the source file and the source line number
 * where the assert_param error has occurred.
 * @PAram file: pointer to the source file name
 * @PAram line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t *file, uint32_t line)
{
 /* USER CODE BEGIN 6 */
 /* User can add his own implementation to report the file name and line number,
 ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
 /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

 

cbarb2747
cbarb2747Author
Associate III
February 18, 2026

Can anyone help me with this?

TDK
Super User
February 18, 2026

osKernelStart does not return. Any code after that call won't be executed.

Create a new OS thread and do what you want in there.

The code says this.

/* We should never get here as control is now taken by the scheduler */
"If you feel a post has answered your question, please click ""Accept as Solution""."
cbarb2747
cbarb2747Author
Associate III
February 18, 2026

Oh man how did I miss that.  I just skimmed past it to the while loop and interrupt functions. Thank you! I will try this out tonight.