Skip to main content
Visitor II
August 18, 2020
Solved

STM32F407 discovery board: Bootloader USART3, General Purpose timer, LED not working

  • August 18, 2020
  • 1 reply
  • 1759 views

Hi

So here's the thing: I've been getting familiar with flashing the STM32F407 discovery board using the in-build bootloader via USART3. Boot mode is set to System memory using

Boot0 = 1 (5V)

Boot1 = 0 (GND)

I am using an USB to serial converter. Connection is:

USB_serial_TX (Green wire) <=> MCU_RX (PC11)

USB_serial_RX (White wire) <=> MCU_TX (PC10)

When using the bootloader to upload a program to control an LCD via I2C, I get the expected result. However, when trying to run a simple GP timer to control an LED, the LED does not blink.

The code itself works, because when using the on-board STLink programmer, the LED blinks. Just with the bootloader, it does not. Any ideas? Thank you.

0693W000003PgUZQA0.png

0693W000003PgUjQAK.jpg

#include "stm32f4xx.h"
 
#if !defined(__SOFT_FP__) && defined(__ARM_FP)
 #warning "FPU is not initialized, but the project is compiling for an FPU. Please initialize the FPU before use."
#endif
 
void funcISRInit();
void funcGPIOInit();
void funcTIM4Init();
 
 
int main(void)
{
	funcISRInit();
	funcGPIOInit();
	funcTIM4Init();
	for(;;);
}
 
void funcISRInit()
{
	// Enable interrupt for TIM4
	__NVIC_EnableIRQ(TIM4_IRQn);
}
 
void funcGPIOInit()
{
	RCC->AHB1ENR |= (1<<RCC_AHB1ENR_GPIODEN_Pos);		// Enables AHB1 to communicate with GPIOD
 
	GPIOD->MODER &= ~(2<<GPIO_MODER_MODER15_Pos);	// PD15 as output	[01]
 
	GPIOD->OTYPER &= ~(1<<GPIO_OTYPER_OT15_Pos);	// Push pull
	GPIOD->OSPEEDR &= ~(3<<GPIO_OSPEEDR_OSPEED15_Pos); // Sets speed on PD12 to low
}
 
void funcTIM4Init()
{
	// Sets PD12 to TIM4
	RCC->AHB1ENR |= (1<<RCC_AHB1ENR_GPIODEN_Pos);		// Enables AHB1 to communicate with GPIOD
	GPIOD->MODER |= (2<<GPIO_MODER_MODER12_Pos);	// Sets PD12 as Alternate function
 
	GPIOD->AFR[1] |= (2<<GPIO_AFRL_AFSEL4_Pos);	// Sets PD12 to AF2 [0010]
 
	// Use PD12 to toggle LED in PWM mode. Use alternate function and TIM4
	RCC->APB1ENR |= (1<<RCC_APB1ENR_TIM4EN_Pos);	// Enables TIM4 on APB1 bus
	TIM4->CR1 |= (1<<TIM_CR1_CEN_Pos);	// CEN: Counter enabled
	TIM4->CR1 &= ~(1<<TIM_CR1_UDIS_Pos);	// UDIS: Update event enabled
	TIM4->CR1 &= ~(1<<TIM_CR1_URS_Pos);	// URS: Update request source enabled
	TIM4->CR1 &= ~(1<<TIM_CR1_OPM_Pos);	// OPM: One pulse mode disabled
	TIM4->CR1 &= ~(1<<TIM_CR1_DIR_Pos);	// DIR: Up count
	TIM4->CR1 &= ~(3<<TIM_CR1_CMS_Pos);	// CMS: Edge aligned mode enabled
	TIM4->CR1 &= ~(1<<TIM_CR1_ARPE_Pos);	// ARPE: Auto reload register not buffered
	TIM4->CR1 &= ~(3<<TIM_CR1_CKD_Pos);	// CKD: Clock division and digital filters set to tdts=tck
 
	TIM4->CR2 &= ~(1<<TIM_CR1_CKD_Pos);	// TIM4_CH1 is connected to TI1 input
 
	TIM4->DIER |= (1<<TIM_DIER_UIE_Pos);	// UIE: Update interrupt enabled
 
	TIM4->EGR |= (1<<TIM_EGR_UG_Pos);	// UG: Update generation enabled
	TIM4->SMCR |= (1<<6);	// TI1F trigger selection
 
	TIM4->CCMR1 &= ~(3<<TIM_CCMR1_CC1S_Pos);	// CC1S: CC1 set as output
	TIM4->CCMR1 |= (2<<TIM_CCMR1_OC1FE_Pos);	// Preload register enabled
	TIM4->CCMR1 |= (6<<TIM_CCMR1_OC1M_Pos);	// OC1M: PWM1 mode [6:4] 110
 
	TIM4->CCER |= (1<<TIM_CCER_CC1E_Pos);	// CC1E: Capture compare 1 output enable
	TIM4->CCER &= ~(1<<TIM_CCER_CC1P_Pos);	// CC1P: Active high
	TIM4->CCER &= ~(1<<TIM_CCER_CC1NP_Pos);	// CC1NP: Cleared because CC1 channel is set to output
 
	TIM4->PSC = 0xF9FF;		// Sets prescaler to 63999. Timer clock is now 16MHz/(63999+1)=250Hz
 
	TIM4->ARR = 0x00F9;		// Counter goes up to 249 to have a 1s timer
 
	TIM4->CCR1 = 0x007D;	// Sets compare match to half of ARR: 50% duty cycle
}
 
void TIM4_IRQHandler()
{
	TIM4->SR &= ~(1<<0);	// Clears UIF bit
	// Handles the IRQ of TIM4
 
	// Toggle LED on PD15
	static uint8_t check = 1;
	if(check)
	{
		GPIOD->BSRR |= (1<<15);
		check = 0;
	}
	else
	{
		GPIOD->BSRR |= (1<<31);
		check = 1;
	}
}

    This topic has been closed for replies.
    Best answer by Tesla DeLorean

    >>Any ideas? 

    Makes sure the vector table points at yours rather than the ROMs

    ie SCB->VTOR = 0x08000000;

    1 reply

    Graduate II
    August 18, 2020

    >>Any ideas? 

    Makes sure the vector table points at yours rather than the ROMs

    ie SCB->VTOR = 0x08000000;

    AAnth.1Author
    Visitor II
    August 18, 2020

    Hi clive1

    You made my day. Inspecting my two projects (the GP timer where the bootloader did not work and the LCD/I2C where the bootloader works), I noticed that my GP timer project did not have the system_stm32f4xx.c file. Copying this file into my GP timer project, my timer now works like a charm via bootloader flash.

    Thanks a lot for your help.

    Cheers,