2022-12-09 11:36 PM
As you can see by the schematic, BOOT0 gets pulled to 3.3V or ground. I pulled it to 3.3V with the switch then held the reset button for several seconds. I currently have a blink program flashed that blinks an LED. When I try to reset the board in bootloader mode, the board just keeps executing the blink program. It will let me program the board just fine the first time, but after that I can't get it back into the bootloader.
To upload the program I'm using a USB to UART converter and the STM32CubeProgrammer application. The resistors on the breadboard pull the data lines up to 3.3V since it uses the pins are USART.
The only issue I could think of is that there should be a resistor between the switch and BOOT0. But I did this when I assembled the next board but that didn't change anything. I still could only flash the first program then it was bricked.
The last thing I can think of that might have an effect is that I compile the code in release mode. Would that have any effect? Should I assemble another board and try uploading the program compiled as debug?
This is my first MCU design, and I'm very new to electronics and PCB design in general. Any feedback is greatly appreciated.
Here's the main.c code:
Pin PC15 is configured as GPIO output.
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2022 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 */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */
void delay (int x);
void blink();
/* 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 */
/* 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();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
blink();
/* 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
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
/** 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.HSIDiv = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_15, GPIO_PIN_SET);
/*Configure GPIO pin : PC15 */
GPIO_InitStruct.Pin = GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
void delay (int x)
{
volatile int i,j;
for (i=0 ; i < x ; i++)
{
j++;
}
return;
}
void blink() {
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_15, GPIO_PIN_RESET);
delay(500000);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_15, GPIO_PIN_SET);
delay(500000);
}
/* 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
* @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 */
Solved! Go to Solution.
2022-12-10 06:09 AM
you need connect a STLink to PA13 + 14 , then you can flash+debug chip.
otherwise:
no bootloader active until you set it in option bytes.
2022-12-10 12:57 AM
Primary your idea miss , first load is possible because empty flash. BOOT and RST pins is shared on your package and defaultly disabled.
Read AN2606
Secondary your design not prepare stlink debug access, that is now only one way for reprogramm.
Maybe you can doo bootloader start with steps disconnect power , hold reset and connect power, release reset, but this is only idea...
2022-12-10 06:09 AM
you need connect a STLink to PA13 + 14 , then you can flash+debug chip.
otherwise:
no bootloader active until you set it in option bytes.
2022-12-10 01:01 PM
Thank you so much for the reply. I actually tried doing just that before. I found out that the issue was that I was using too high of a SW clock frequency. My board can only tolerate a maximum frequency of 15kHz. Once I lowered the frequency to 15kHz, I was able to get the ST-Link to finally connect.
Just out of curiosity, where did you find that image, I must have missed that when I was reading the datasheet.
2022-12-10 01:11 PM
is in ds , footnote :
no. 5 :+
15khz ? there is another problem in your setup, STLink runs at 4MHz standard.
but if you get it running...ok.
2022-12-10 06:16 PM
The wiring for the programmer is fine. I believe the issue is the way I designed the PCB. To wire the SWCLK to PA14, I had to remove the boot switch from the board and solder a pin to the pad directly. The issue I think comes with the trace that the SWCLK signal has to traverse to get to the MCU pin. The trace is relatively long, switches between layers, and has other traces running across it splitting the ground plane. From my understanding those are all huge issues regarding signal integrity. So to resolve that issue I have to decrease the clock frequency (essentially the AC frequency) to overcome those issues.
In short, if I'd laid out the board better so that the SWCLK and SWDIO pins are directly next to the MCU I'd have less issues. But because I didn't, I have to dramatically decrease the clock frequency, which isn't a huge deal, just kind of annoying.
Below are some drawing to illustrate what I'm talking about. The top is how I wired the programmer to the board. the bottom shows the path that SWCLK has to traverse on the PCB to reach PA14. The pink X's mark where the trace switches layers and cross other traces. (path on top layer in green, path on bottom in blue)
2022-12-10 11:07 PM
just - did you remove the cap C3 and the R or led ? this would make stlink very slow.
and
for next design: (in Cube) first activate swd , then all other things you want.
and for circuit/layout make swd connector, not too far away from cpu (crossing some tracks on other layer is no big problem).
and about your circuit:
2022-12-13 09:42 PM
UPDATE. To test if the routing/placement was the issue I wired a pin directly to PA14 (SWCLK) and tried to run ST-LINK at full speed, this worked. So I believe the signal switching layers and crossing traces was likely the issue I was having.
Here's a diagram of exactly how I wired the programmer.
After this I was able to use the full 4Mhz clock cycle instead of the 15kHz I was using.
2022-12-13 09:51 PM
I used two regulators thinking that this way I could be sure I'd have enough current capacity since I wasn't sure how much the MCU would draw, in the next iteration I'll only use one. As for the capacitors, I used multiple decoupling capacitors because this is what I saw on many open-source boards and what many resources recommended, I can't directly speak on its effects on oscillations, but in theory it should widen our the low impedance band for our supply. The 4.7uF and 100nF caps were derived from AN5096, Getting Started with STM32G0 Hardware Development. The only other thing I might change in the next design is bringing the ferrite-bead in closer to the MCU supply pins.
2022-12-13 10:25 PM