Skip to main content
Associate
July 16, 2026
Question

STM32N657X0-Q: ADC1 Calibration fails (HAL_ERROR 1) and returns 0 despite RIFSC Non-Secure configuration and CN12 jumpers connected

  • July 16, 2026
  • 2 replies
  • 27 views

Hi ST Community,

I am currently working on an analog sensor acquisition project using the NUCLEO-N657X0-Q (STM32N657X0) board on STM32CubeIDE (version 1.19.0). I am attempting to read a Keyes pressure sensor via ADC1 on PA1 (ADC1_INP1).

Physical Wiring & Setup

  • Sensor Connections: The pressure sensor is physically wired to:

    • VCC -> Board 3.3V

    • GND -> Board GND

    • Signal Out -> PA1 (bridged with a 1/2 resistor divider to ground to ensure the voltage never exceeds 1.8V).

  • CN12 Jumpers Connected:

    • Pin 13 / Pin 14 (VDDA1V8) is connected with a jumper cap to supply 1.8V to VDDA.

    • Pin 11 / Pin 12 (VDDIO) is connected with a jumper cap.

 STM32CubeMX Configurations

  1. VREFBUF: Configured as Disable (since the NUCLEO board provides an external 1.8V reference to VREF+).

  2. Security & RIF (RIFSC Panel):

    • ADC1: Configured as Non-Secure, Unprivileged (unchecked), Unlock (unchecked), and assigned to the Application context.

    • GPIOA: Configured as Non-Secure, Unprivileged (unchecked), and assigned to the Application context.

  3. ADC1 Parameters: 12-bit Resolution, Scan Conversion Mode Disabled, Continuous Conversion Mode Disabled, Software Trigger.

 Symptom & Error Logs

During system startup, HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED) consistently fails and returns HAL_ERROR (Status Code 1).

When running the main loop, the returned values are always 0:

============================================
STM32N657X0-Q Keyes Pressure Sensor Demo
System Core Clock: 64000000 Hz
============================================
[VREF] NUCLEO-N657X0-Q board provides an external 1.8V analog reference (VREF+).
[VREF] Software bypassed VREFBUF (Disabled) to avoid Secure World register lock.
[ADC1] Starting hardware self-calibration...
[ADC1] WARNING: Calibration failed! Error Code: 1
-> 🚨 Please troubleshoot based on the following checklist:
1. [JUMPERS] Verify CN12 Pin 13 & Pin 14 (VDDA1V8) are connected with a jumper cap.
(R104 is OFF by default; bridging CN12 13-14 is mandatory to power the analog core!)
2. [JUMPERS] Verify CN12 Pin 11 & Pin 12 (VDDIO) are connected with a jumper cap.
3. [FIREWALL] Confirm ADC1 and GPIOA are configured as Non-Secure / Unprivileged in CubeMX RIF Panel.
4. [CLOCKS] Ensure 'ADC Source Mux' is pointing to a valid clock (e.g. HSIDIV, CLK_KER <= 50MHz).
[Keyes Sensor] RAW Value: 0 | Calculated Voltage: 0.000 V
[Keyes Sensor] RAW Value: 0 | Calculated Voltage: 0.000 V

💻 Code Snippet (main.c)

Here is my non-secure application code used for sampling:

/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body - ADC1 Pressure Sensor Sampling
******************************************************************************
* @attention
*
* Copyright (c) 2026 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"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h> // Include standard I/O library for printf support
/* 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 ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;

UART_HandleTypeDef huart1;

/* USER CODE BEGIN PV */
uint32_t adc_raw_val = 0; // Stores 12-bit raw ADC reading (0 ~ 4095)
float sensor_voltage = 0.0f; // Stores physical voltage (V) after 1/2 divider compensation
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_USART1_Init(void);
/* USER CODE BEGIN PFP */
float Read_Keyes_Pressure_PA1(void); // Function prototype for pressure sensor reading
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
#ifdef __GNUC__
/* Redirect __io_putchar to UART register for GCC compilers */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

PUTCHAR_PROTOTYPE
{
/* Transmit one character via USART1 with max delay timeout */
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}

/* Overwrite standard write function to ensure smooth float and string printf output */
int _write(int file, char *ptr, int len)
{
HAL_UART_Transmit(&huart1, (uint8_t *)ptr, len, HAL_MAX_DELAY);
return len;
}
/* USER CODE END 0 */

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

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

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

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

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_USART1_Init();
/* USER CODE BEGIN 2 */

/* --- [1] Initialize Serial Terminal Header --- */
printf("\r\n============================================\r\n");
printf(" STM32N657X0-Q Keyes Pressure Sensor Demo\r\n");
printf(" System Core Clock: %lu Hz\r\n", HAL_RCC_GetSysClockFreq());
printf("============================================\r\n");

/* --- [2] Reference Voltage Mode Notification --- */
printf("[VREF] NUCLEO-N657X0-Q board provides an external 1.8V analog reference (VREF+).\r\n");
printf("[VREF] Software bypassed VREFBUF (Disabled) to avoid Secure World register lock.\r\n");

/* --- [3] Stabilization Delay --- */
// Delay 50ms to ensure VDDA1V8 power rail and clock supply are fully stabilized
HAL_Delay(50);

/* --- [4] STM32N657X0 Hardware Self-Calibration --- */
printf("[ADC1] Starting hardware self-calibration...\r\n");
HAL_StatusTypeDef cal_status = HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
if (cal_status != HAL_OK)
{
printf("[ADC1] WARNING: Calibration failed! Error Code: %d\r\n", cal_status);
printf(" -> 🚨 Please troubleshoot based on the following checklist:\r\n");
printf(" 1. [JUMPERS] Verify CN12 Pin 13 & Pin 14 (VDDA1V8) are connected with a jumper cap.\r\n");
printf(" (R104 is OFF by default; bridging CN12 13-14 is mandatory to power the analog core!)\r\n");
printf(" 2. [JUMPERS] Verify CN12 Pin 11 & Pin 12 (VDDIO) are connected with a jumper cap.\r\n");
printf(" 3. [FIREWALL] Confirm ADC1 and GPIOA are configured as Non-Secure / Unprivileged in CubeMX RIF Panel.\r\n");
printf(" 4. [CLOCKS] Ensure 'ADC Source Mux' is pointing to a valid clock (e.g. HSIDIV, CLK_KER <= 50MHz).\r\n");
}
else
{
printf("[ADC1] Calibration successful! System is ready for data acquisition.\r\n");
}

/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* --- [5] Periodic Sampling and Logging --- */
sensor_voltage = Read_Keyes_Pressure_PA1();

// Log formatted data
printf("[Keyes Sensor] RAW Value: %4lu | Calculated Voltage: %.3f V\r\n",
adc_raw_val, sensor_voltage);

// Delay 250ms to prevent flooding the terminal
HAL_Delay(250);
/* USER CODE END WHILE */

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

/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Configure the main internal regulator output voltage
*/
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
{
Error_Handler();
}

/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}

/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_PCLK4|RCC_CLOCKTYPE_PCLK5;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB4CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB5CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct) != HAL_OK)
{
Error_Handler();
}
}

/**
* @brief ADC1 Initialization Function
* @param None
* @retval None
*/
static void MX_ADC1_Init(void)
{

/* USER CODE BEGIN ADC1_Init 0 */

/* USER CODE END ADC1_Init 0 */

ADC_ChannelConfTypeDef sConfig = {0};

/* USER CODE BEGIN ADC1_Init 1 */

/* USER CODE END ADC1_Init 1 */

/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}

/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_11CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */

/* USER CODE END ADC1_Init 2 */

}

/**
* @brief USART1 Initialization Function
* @param None
* @retval None
*/
static void MX_USART1_Init(void)
{

/* USER CODE BEGIN USART1_Init 0 */

/* USER CODE END USART1_Init 0 */

/* USER CODE BEGIN USART1_Init 1 */

/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */

/* USER CODE END USART1_Init 2 */

}

/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
/* USER CODE BEGIN MX_GPIO_Init_1 */

/* USER CODE END MX_GPIO_Init_1 */

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();

/* USER CODE BEGIN MX_GPIO_Init_2 */

/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */
/**
* @brief Reads PA1 (ADC1_INP1) pressure sensor voltage and prints diagnostics.
* @note STM32N657X0 ADC Reference (VREF+) is 1.8V.
* If the external hardware uses a 1/2 resistor divider to ground (protecting PA1 from >1.8V),
* this algorithm multiplies by 2.0f to reconstruct the true sensor voltage on 3.3V power rail.
* @retval float Compensated real voltage (V)
*/
float Read_Keyes_Pressure_PA1(void)
{
uint32_t raw_data = 0;
float calculated_vol = 0.0f;
HAL_StatusTypeDef start_status;
HAL_StatusTypeDef poll_status;

// 1. Start ADC1 Single conversion (Software trigger)
start_status = HAL_ADC_Start(&hadc1);
if (start_status == HAL_OK)
{
// 2. Poll for ADC conversion completion with 20ms timeout defense
poll_status = HAL_ADC_PollForConversion(&hadc1, 20);
if (poll_status == HAL_OK)
{
// 3. Read 12-bit ADC conversion result (0 ~ 4095)
raw_data = HAL_ADC_GetValue(&hadc1);
adc_raw_val = raw_data; // Synchronize to global variable

// 4. Reconstruct sensor output voltage
// Formula: (ADC raw / 4095) * ADC Reference (1.8V) * Divider compensation (2.0)
calculated_vol = ((float)raw_data / 4095.0f) * 1.8f * 2.0f;
}
else
{
// Diagnostic output on poll failure (capped at once every 5 seconds to prevent spam)
static uint32_t last_poll_log = 0;
if (HAL_GetTick() - last_poll_log > 5000)
{
printf("[ADC1 Log] PollForConversion Failed! HAL Status: %d\r\n", poll_status);
printf(" -> Ensure the clock tree 'ADC Source Mux' is correctly configured (e.g., HSIDIV).\r\n");
last_poll_log = HAL_GetTick();
}
}

// 5. Stop ADC conversion to save power and prepare for next iteration
HAL_ADC_Stop(&hadc1);
}
else
{
// Diagnostic output on start failure (capped at once every 5 seconds)
static uint32_t last_start_log = 0;
if (HAL_GetTick() - last_start_log > 5000)
{
printf("[ADC1 Log] HAL_ADC_Start Failed! HAL Status: %d\r\n", start_status);
printf(" -> Register write blocked! Verify RIFSC permissions for ADC1 and GPIOA are assigned to Application.\r\n");
last_start_log = HAL_GetTick();
}
}

return calculated_vol;
}
/* USER CODE END 4 */

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

 Questions

Since the RIFSC has already been configured to assign ADC1 and GPIOA to the Non-Secure Application context, and the physical power rails are properly jumpered:

  1. Is there any additional system power configuration (e.g., PWR or clock gating) required to enable the ADC1 analog domain or internal voltage regulator for non-secure applications on STM32N6?

  2. Does the STM32N6 ADC hardware calibration require specific clock speed constraints or a specific prescaler setup to pass?

Any advice, hints, or ADC reference examples for the STM32N6 series would be highly appreciated.

Best regards,

 

2 replies

Associate
July 16, 2026

Hello, members of the ST community!

I am developing an application on the NUCLEO-N657X0-Q (STM32N657X0) using the STM32Cube IDE. I am attempting to read data from a pressure sensor (Keyes FSR) via ADC1 (PA1).

Problem: My code is getting stuck at the point where HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED)returns a HAL_ERROR((code 1). The raw value is always 0.

Current configuration and debugging steps

  1. Hardware:

    • I have verified the physical connections on CN12((pins 13/14 of VDDA1V8 and pins 11/12 of VDDIO are connected via jumpers).

    • I have confirmed that the sensor input voltage is within the 0–1.8 V range.

  2. CubeMX RIF settings:

    • I have accessed the RIF panel in CubeMX.

    • For ADC1 and GPIOA: I have ensured they are set to ‘non-secure’ mode and have assigned the runtime context to ‘Application’. I have also disabled the ‘Privileged’ and ‘Locked’ attributes.

  3. Software Configuration:

    • VREFBUFmode is set to disabled, as the board provides an external 1.8V reference voltageVREF

    • ADC1 is configured in single-ended mode.

Issue: Despite disabling VREFBUF and setting the RIFSC permissions for ADC1 and GPIOA to the application context, hardware calibration still fails with HAL_ERROR (1)

ADVREGEN I suspect that the internal voltage regulator of ADC1 in the STM32N6 series may have hidden RIF restrictions or a specific initialisation sequence, which differs from previous STM32 generations.

Could you please provide guidance on the following

  1. Is additional RIFSC or system-level configuration required to run ADC1 in non-secure mode on the STM32N6?

  2. Is there a recommended initialization sequence for ADC1 on the Cortex-M55 core to ensure the internal analogue LDO is correctly initialized prior to calibration?

Attached are my RIF configuration and initialization code snippets. Many thanks for any advice you can offer.

Yours sincerely, Michael Hong

 

*This post has been translated from Chinese to comply with the ST Community guidelines.

ST Technical Moderator
July 21, 2026

Hello ​@Michael Hong 

Please refer to the example below, which demonstrates how to use an ADC peripheral to convert multiple channels. The example also includes the configuration of the Resource Isolation.

STM32CubeN6/Projects/NUCLEO-N657X0-Q/Examples/ADC/ADC_MultiChannelSingleConversion at main · STMicroelectronics/STM32CubeN6

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Saket_Om
mƎALLEm
ST Technical Moderator
July 20, 2026

Hello ​@Michael Hong and welcome to the ST community,

I’ve merged your threads as you have duplicated the same post on the same problem in different threads.

In next time please avoid duplication threads for the same issue problem. Just create one post and add post if you have further information. Thank you for your understanding.

To give better visibility on the answered topics, please click "Best answer" on the reply which solved your issue or answered your question.