2024-08-15 08:06 AM
Hello,
I am using a bog standard, new, out of the box Nucleo-wba52cg.
For some reason I can't get PA8 aka GPIO_23 to pull lower than about 1.6V?
I discovered this when running the TIM_OCToggle example program. TIM_OCToggle uses TIM2 to toggle pins on each of the TIM2_CHANNEL_X pins. All of the channels are working as expected except that TIM_CHANNEL_2/PA8/GPIO_23 never got fully low. The signal is high at 3.3V as expected, but low is 1.6V, which is not expected and not gonna work for my app.
I've tried to narrow down the issue using a variety of other out-of-the-box examples. Perhaps the simplest is GPIO_IOToggle. I've modified it to toggle PA8 in addition to PA7.
I'm still seeing a low value of 1.6V?
Here is the main.c file from the modified GPIO_IOToggle example with 1 line modified (113), and one added(137)... both labeled MODIFIED in comments...
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file GPIO/GPIO_IOToggle/Src/main.c
* @author MCD Application Team
* @brief This example describes how to configure and use GPIOs through
* the STM32WBAxx HAL API.
******************************************************************************
* @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"
/* 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 ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
static GPIO_InitTypeDef GPIO_InitStructA;
static GPIO_InitTypeDef GPIO_InitStructB;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ICACHE_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* STM32WBAxx HAL library initialization:
- Systick timer is configured by default as source of time base, but user
can eventually implement his proper time base source (a general purpose
timer for example or other time source), keeping in mind that Time base
duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
handled in milliseconds basis.
- Set NVIC Group Priority to 4
- Low Level Initialization
*/
/* 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_ICACHE_Init();
/* USER CODE BEGIN 2 */
/* -1- Enable GPIO Clock (to be able to program the configuration registers) */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/* -2- Configure IO in output push-pull mode to drive external LEDs */
GPIO_InitStructA.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructA.Pull = GPIO_NOPULL;
GPIO_InitStructA.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStructA.Pin = GPIO_PIN_7 | GPIO_PIN_8; // MODIFIED originally GPIO_PIN_7
HAL_GPIO_Init(GPIOA, &GPIO_InitStructA);
/* -2- Configure IO in output push-pull mode to drive external LEDs */
GPIO_InitStructB.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructB.Pull = GPIO_NOPULL;
GPIO_InitStructB.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStructB.Pin = GPIO_PIN_15;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructB);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_15);
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_7);
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_8); // MODIFIED added to original example
/* Insert delay 100 ms */
HAL_Delay(500);
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Supply configuration update enable
*/
HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
/** Configure the main internal regulator output voltage
*/
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEDiv = RCC_HSE_DIV1;
RCC_OscInitStruct.PLL1.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL1.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL1.PLLM = 4;
RCC_OscInitStruct.PLL1.PLLN = 25;
RCC_OscInitStruct.PLL1.PLLP = 2;
RCC_OscInitStruct.PLL1.PLLQ = 2;
RCC_OscInitStruct.PLL1.PLLR = 2;
RCC_OscInitStruct.PLL1.PLLFractional = 0;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_PCLK7|RCC_CLOCKTYPE_HCLK5;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB7CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.AHB5_PLL1_CLKDivider = RCC_SYSCLK_PLL1_DIV4;
RCC_ClkInitStruct.AHB5_HSEHSI_CLKDivider = RCC_SYSCLK_HSEHSI_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief ICACHE Initialization Function
* @PAram None
* @retval None
*/
static void MX_ICACHE_Init(void)
{
/* USER CODE BEGIN ICACHE_Init 0 */
/* USER CODE END ICACHE_Init 0 */
/* USER CODE BEGIN ICACHE_Init 1 */
/* USER CODE END ICACHE_Init 1 */
/** Enable instruction cache in 1-way (direct mapped cache)
*/
if (HAL_ICACHE_ConfigAssociativityMode(ICACHE_1WAY) != HAL_OK)
{
Error_Handler();
}
if (HAL_ICACHE_Enable() != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ICACHE_Init 2 */
/* USER CODE END ICACHE_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 */
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
/* 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 */
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) */
/* Infinite loop */
while (1)
{
}
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
Here is the output I am seeing. Blue is GPIO_11/PA7 which is working correctly. Yellow is GPIO_23/PA8 which is not falling close enough to GND.
Suggestions?
Bill
2024-08-15 08:29 AM
It appears that pin is connected to VCP1_RX:
2024-08-15 08:55 AM
Yes! I see that in the schematic.
That said, a search for "VCP" in the reference manual turns up "0" hits.
It seem to have something to do with a UART... which I am not using in anyway... except perhaps as a debug interface? But if it PA8 was being used for some debugging communication I would expect to see it wiggling, or for debugging to get screwy when I tried to toggle the PA8 pin. I don't see any of that.
So, I guess the question becomes, what is VCP_1RX, and how do I get it to stop messing with my PA8 pin?
Aside: Somewhat odd that an example project designed to show proper use of these pins (TIM_OCToggle which was specifically called out for this board) should not address this VCP_1RX issue... if that is indeed what the issue is.
Thank you,
Bill
2024-08-15 09:01 AM
Remove SB2 (SB = Solder Bridge).
2024-08-15 09:03 AM
SB21, not SB2...
2024-08-15 09:17 AM
Huh... remove SB21?
Perhaps I am looking at the wrong document? I have been referencing this document...
https://www.st.com/resource/en/schematic_pack/mb1863-wba52cga-a03-schematic.pdf
On the 3rd page is the following diagram...
I'm still pretty new to STM32 but in my reading, this seems to show that if I remove SB21, then PA8 will no longer be connected to GPIO23? It does not appear to indicate that the influence of VCP1_RX on PA8 will be effected at all?
Would you please explain a bit more about how removing SB21 would address this issue?
Thank you,
Bill
2024-08-15 09:30 AM
Well, that schematic is not too clear, but it looks like removing SB21 could disconnect PA8 from everything; you should be able to confirm that looking at the actual board.
Removing SB17 and adding SB19 will connect PA8 to GPIO21.
2024-08-15 11:35 AM
Ah, okay! That did it.
I guess it seems the Nucleo board is doing something on GPIO_23 that is not documented in the schematic?
It seems that I maybe could have also removed SB5 to disconnect VCP1_RX from GPIO_23. Digging further, it is clear that the VCP1_RX has something to do with the STLink, but what exactly is still unclear to me.
Regardless, debugging still works and GPIO_21 is now working as expected after the re-configuration of the solder bridges as you suggest.
Thank you,
Bill
2024-08-15 11:43 AM
I believe VCP is a feature where a virtual COM port is produced by the STLink that allows your micro to send data via USART pins (e.g., PA8) which appears at COMx on your PC.
The user manual describes this, somewhat: