Project demo on STM32F103RBT6 using GCC

STM32F103R board is a simple and easy development board to learn STM32 microcontroller programming. Its heart is STM32F103RBT6 ARM Cortex-M3 microcontroller with 128K of Flash and 20K of SRAM memory. It can be clocked at maximum 72MHz frequency and is considered to be a medium-density performance line microcontroller. Other features include USB, CAN, 7 timers, 2ADCs and 9 communication interfaces.

Development board has several nice features to get started with. First of all it has RS232 interface for communicating and accessing bootloader. There also is a USB 2.0 full speed interface connector that also can work as power supply. Next is a JTAG connector to program microcontroller using tools like J-Link adapter. Two push buttons and two progammable LEDs are hardwired to MCU pins alongside all I/Os connectors.

In order to start programming this microcontroller we need to set up a project template which can be used for further developments. We like GCC tools so grab Courcery CodeBench Lite Edition and Eclipse IDE to get started.

We won’t be reinventing wheel and stick to what’s been done. As a reference we can take our previous project on STM32F103ZET6 development board. The main difference between those microcontrollers are that current is medium-density and earlier were high-density with more features and more memory. So few small changes has to be done in linker script and interrupt vectors table. As always Michael Fischer has done the hard work and prepared those files. To get these you can download STM32F103RB project files for yagarto and extract files. We will need stm32f103xb_flash.ld and stm32f103xb_ram.ld and make sure that memory configuration is right:

MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
}

Also we will need a crt.c and vectors_stm32f10x_hd.c files (Don’t worry you will find all files in a project package). The rest procedure is same as in STM32F103ZET6 project mentioned earlier. Lets focus on hardware programming. First of all lets take care of buttons. Here on board are two push buttons connected between PC0 and PC1 pins and ground:

Using CMSIS writing button driver is easy. First buttons.h file:

#ifndef BUTTONS_H_
#define BUTTONS_H_
#include "STM32f10x.h"
#define BS2 				GPIO_Pin_0
#define BS3 				GPIO_Pin_1
#define BPORT				GPIOC
#define BPORTCLK			RCC_APB2Periph_GPIOC
void ButtonsInit(void);
uint32_t ButtonRead(GPIO_TypeDef* Button_Port, uint16_t Button);
#endif /* BUTTONS_H_ */

Then we can write functions in buttons.c file:

#include "buttons.h"
void ButtonsInit(void)
{
  //GPIO structure used to initialize Button pins
  GPIO_InitTypeDef GPIO_InitStructure;
  //Enable clock on APB2 pripheral bus where buttons are connected
  RCC_APB2PeriphClockCmd(BPORTCLK,  ENABLE);
  //select pins to initialize S2 and S3 buttons
  GPIO_InitStructure.GPIO_Pin = BS2|BS3;
  //select pull-up input mode
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  //select GPIO speed
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(BPORT, &GPIO_InitStructure);
}
uint32_t ButtonRead(GPIO_TypeDef* Button_Port, uint16_t Button)
{
  return !GPIO_ReadInputDataBit(Button_Port, Button);
}

Here when initializing buttons we first enable APB2 peripheral clock then we set internal pull-up resistors for button pins and set I/O speed.

Next we can write LED drivers. LEDs are connected between PB8, PB9 and VCC as follows:

Initialize LEDs with following function in leds.c:

void LEDsInit(void)
{
  //GPIO structure used to initialize LED port
  GPIO_InitTypeDef GPIO_InitStructure;
  //Enable clock on APB2 pripheral bus where LEDs are connected
  RCC_APB2PeriphClockCmd(LEDPORTCLK,  ENABLE);
  //select pins to initialize LED
  GPIO_InitStructure.GPIO_Pin = LED1|LED2;
  //select output push-pull mode
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  //select GPIO speed
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(LEDPORT, &GPIO_InitStructure);
  //initially LEDs off
  GPIO_SetBits(LEDPORT, LED1|LED2);
}

and implement three control functions:

voidLEDOn(uint32_t);

voidLEDOff(uint32_t);

voidLEDToggle(uint32_t);

To test if everything works we can write simple routine in main.c:

#include "stm32f10x.h"
#include "leds.h"
#include "buttons.h"
//delay function
void Delay(__IO uint32_t nCount)
{
  for(; nCount != 0; nCount--);
}
int main(void)
{
  //init leds
  LEDsInit();
  ButtonsInit();
while (1)
  {
	//read S2 button
	if (ButtonRead(BPORT, BS2))
	{
		//led 1 on
		LEDOn(1);
		//delay
		Delay(2000000);
		//led 1 off
		LEDOff(1);
	}
	//read S3 button
	if (ButtonRead(BPORT, BS3))
	{
		//led 2 on
		LEDOn(2);
		//delay
		Delay(3000000);
		//led 2 off
		LEDOff(2);
	}
  }
}

Here we simply turn LED after button is pressed and it turns off automatically after some delay.

When compiling program with newest CodeBench Lite strange error popped out:

Error: registers may not be the same -- `strexh r0,r0,[r1]'
Error: registers may not be the same -- `strexb r0,r0,[r1]'

Arm specification require that Rd register must be different from Rt and Rn and CMSIS seems not following this. So in order to fix this you need to modify core_cm3.c file as follows:

replace:

uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
uint32_t result=0;
__ASM volatile ("strexh %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
}

with

uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
//uint32_t result=0;
register uint32_t result asm ("r2");
__ASM volatile ("strexh %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
}

and replace:

uint32_t __STREXB(uint8_t value, uint8_t *addr)
{
uint32_t result=0;
__ASM volatile ("strexb %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
}

with:

uint32_t __STREXB(uint8_t value, uint8_t *addr)
{
//uint32_t result=0;
register uint32_t result asm ("r2");
__ASM volatile ("strexb %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
}

for more information refer to old.nabble.com. After this change code compiles fine. Flash microcontroller using Flash loader demonstrator or via JTAG and run. Download project template if you wanna try it by yourself: [STM32F103R_Buttons_LEDs ~660K]

Leave a Reply

Your email address will not be published. Required fields are marked *