Hello Everyone,
I am total newbie. I recently got a STM32 discovery board from a local FAE. I was wondering if i could flash the Maple bootloader on to the STM32 discovery board?
thanks in advance,
ultrasounder
Hello Everyone,
I am total newbie. I recently got a STM32 discovery board from a local FAE. I was wondering if i could flash the Maple bootloader on to the STM32 discovery board?
thanks in advance,
ultrasounder
I just picked up one of those STM32 Discovery boards myself, and had been wondering about the same possibility. Unfortunately, I don't think it will work. The problem is that the Discovery board contains not one but two Cortex-M3 microcontrollers. The larger of the two is an STM32F100RB, and the header pins all around the edge of the board are connected to its IO ports, but it is not connected to the USB port. The smaller chip is an STM32F103C8T6; it owns the USB port, but none of its IO pins are available. It is basically a built-in programming circuit for the larger chip.
The larger chip on the Discovery board thus does not have any bootloader at all: it expects to be reprogrammed externally. The smaller chip doesn't really have a bootloader either: its own code never changes, and it just uploads things to the larger chip.
The Maple bootloader is designed for a single-chip board, so that the chip can download and install programs onto itself. This works for the Maple board because the USB port is connected directly to the controller. This is not the case for the Discovery board.
What we need for the Discovery board is a serial bootloader, and the STM32F100RB on the board just happens to include one in ROM. I haven't tried it yet, but people have apparently had some success getting access to this bootloader via USART1 (that is, pins PA9 and PA10). You'll need a USB-serial interface adapter (like the ubiquitous FTDI232RL), and you'll have to remove one of the solder bridges.
Hi,
As Mars Saxman say, there's a built in bootloader in the STM32's that can be used for programming. But it isn't compatible with the maple bootloader. If you want to use it for programming, you don't need to desolder anything. Just connect the "boot" pin to 3V3 and hit reset, and the STM32F100 will go into the bootloader.
One could probably port the libmaple-stuff to the discovery board and upload "sketches" with the serial bootloader (or with the USB ST-link if you use Windows). It would be some work but not impossible. But I don't think anyone have done that. (And I don't think leaflabs is interested in doing it, they probably want to sell the hardware too).
So my suggestion is, if you want to get things done, buy a Maple (or two, as I did). And if you want to get into the lower level details you try that on the discovery board (or on the Maple(s), you can do that there too).
As pointed out above, there are two processors on the discovery board - an stm32f103
which provides the st-link capability and an stm32f100 which is the application processor.
The stm32f100 doesn't have a usb port, so there's no advantage to the bootloader.
You can replace the firmware on the stm32f103 -- but you have to give up the st-link.
At the moment, there isn't a useful firmware replacement and the stm32f103 only
has a few connections -- to the swd inteface of the stm32f100.
Here's a nice tutorial on reflashing the stm32f103 -- http://takenapart.com/?p=82
You do need to be able to solder fine wires and have another board to do the reflashing.
The maple bootloader will work on the stm32f103 with a few modifications -- the led and
button pins differ. Also, there's no soft disconnect circuitry so it isn't feasible
to switch between dfu and serial modes under software control. I modified the bootloader to go directly to user code (without initializing the usb connection for dfu)
if the button is not pressed.
It is feasible to write applications for the stm32f103 with the maple IDE, but there
isn't a lot of I/O available (just the few swd pins).
However, if one is looking for a starting point for new firmware for the stm32f103, this
might be a good first step.
I use Maple IDE to compile for Discovery but using STM32 ST-Link Utility for firmware downloading. It not so comfortably but it works, at least in simple examples.
I added section in boards.txt with:
discovery.name=Discovery to FLASH
discovery.upload.ram.maximum_size=8000
discovery.build.f_cpu=24000000L
discovery.build.linker=maple/discovery.ld
in libmaple.h :
#define USER_ADDR_ROM 0x08000000
in maple/discovery.ld :
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
in wirish.c :
rcc_clk_init(RCC_CLKSRC_PLL, RCC_PLLSRC_HSE, RCC_PLLMUL_3); //24 MHz
and comment out setupUSB();
in boards.h :
#define CYCLES_PER_MICROSECOND 24
#define SYSTICK_RELOAD_VAL 23999 /* takes a cycle to reload */
#define BOARD_BUTTON_PIN 2 /* PA0 USER */
#define BOARD_LED_PIN 37 /* blue led LD4 */
Also it is possible to load firmware using console util APIsample.exe from STM programming toolkit.
PS
clk_speed = (usart_num == USART1) ? 24000000UL : 12000000UL;
in usart.c
Anton, could you upload these modified files?
Where?
I've successfully made the changes above, although I compile from the command line. I have
a few observations.
-- some of the processor specific configuration information is scattered throughout the
code base. Some code refactoring could make adding new stm32 processors a lot easier
An example is the way timers are handled. There's a hack (NR_TIMERS) to handle the two
cases leaf labs has run into, but it really doesn't scale. For example, the value line
parts have additional timers that simply don't fit into this model.
-- it really is advisable to add a new PIN_MAP to wirish/boards.h for the discovery board.
I took the opportunity to define an enum {PA0, PA1, PA2, PA3, PA4,.... and reorder
the table entries to match this enum. This makes sense for the discovery board where
pins are labled by with the GPIO port names. BTW, this whole indexed table
business is pretty traditional c. Once the decision was made to go down the
c++ path for wirish, this could be done in much cleaner ways that let the linker do
some of the heavy lifting.
On the plus side -- the basic demo example worked out of the can with a few redefinitions
of pins, although the PWM didn't . I especially liked having a UART working.
Oh, I also had to change the make files to leave out all the USB stuff which gets
built into the binary by default and is not useful for the discovery board.
I agree that it is unconvenient to have for example frequency related constants (f_cpu RCC_PLLMUL_9 RCC_APB1_HCLK_DIV_2 RCC_APB2_HCLK_DIV_1 CYCLES_PER_MICROSECOND SYSTICK_RELOAD_VAL 72000000UL 36000000UL PCLK1 PCLK2 36) in different files.
Good idea about aliases for pin numbers.
I think that is easier to define an enum {PA3, PA2, PA0.
Maybe it's time to create a git branch for discovery?
I have not tried PWM but Servo library works.
I also found that delay(1) in fact givs 1.5 ms.
geoffreymbrown,
We very much agree that the current master branch of libmaple is pretty hackish with regards to scaling to multiple boards. We have recently been addressing this issue in the "refactor" branch:
https://github.com/leaflabs/libmaple/commits/refactor
This branch is a very heavy refactor of the low-level "libmaple proper" library (i.e., the pure C library, rather than the "wirish" Arduino-style compatibility layer).
I haven't had time yet to finish writing the design document for the refactor branch (partially because the design isn't final yet), but have a look around; hopefully you'll be pleased with how things are going.
Hi,
Extending Anton's setup for using the Discovery with the LeafLabs IDE, this should open up all 51 I/O pins on the Discovery without stepping on the Maple board definitions. The external interrupts are undefined at this time.
1) Add this code block to hardware->leaflabs->boards.txt
##############################################################
discovery.name=Discovery to FLASH
discovery.upload.file_type=bin
discovery.upload.maximum_size=128000
discovery.upload.ram.maximum_size=8000
discovery.upload.flash.maximum_size=128000
discovery.build.board=maple_discovery
discovery.build.mcu=STM32F100RB
discovery.build.family=cortex-m3
discovery.build.f_cpu=24000000L
discovery.build.core=maple
discovery.build.vect=VECT_TAB_BASE
discovery.build.linker=discovery/flash.ld
discovery.build.using=armcompiler
2) Create a directory folder called 'discovery' at
hardware->leaflabs->cores->maple
3) Copy the flash.ld file from the maple folder into the discovery folder.
4) Make these changes to hardware->leaflabs-cores->maple->discovery->flash.ld
/* Define memory spaces. */
MEMORY
{
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
}
5) Add this codeblock to hardware->leaflabs->cores->maple->libmaple.h
#ifdef MCU_STM32F100RB
/* e.g., STM32VLDISCOVERY -------------------*/
/* Number of GPIO ports (GPIOA, GPIOB, etc.) */
#define NR_GPIO_PORTS 4
/* Total number of GPIO pins */
#define NR_GPIO_PINS 51
/* Number of timer devices ports, definitely used */
#define NR_TIMERS 4
/* Number of USART ports */
#define NR_USART 3
/* Has an FSMC bus? */
#define NR_FSMC 0
/* Has an FSMC bus? */
#define NR_DAC_PINS 0
/* USB Identifier numbers */
/* Descriptor strings must be modified by hand in
usb/descriptors.c for now */
#define VCOM_ID_VENDOR 0x1EAF
#define VCOM_ID_PRODUCT 0x0004
#define USB_DISC_BANK GPIOC_BASE
#define USB_DISC_PIN 12
#define USB_CONFIG_MAX_POWER (100 >> 1)
#define RESET_DELAY (100)
/* Where to put usercode (based on space reserved for bootloader) */
#define USER_ADDR_ROM 0x08000000
#define USER_ADDR_RAM 0x20000C00
#define STACK_TOP 0x20000800
/* Debug port settings (from ASSERT) */
#define ERROR_LED_PORT GPIOA_BASE
#define ERROR_LED_PIN 5
#define ERROR_USART_NUM USART2
#define ERROR_USART_BAUD 9600
#define ERROR_TX_PORT GPIOA_BASE
#define ERROR_TX_PIN 2
/* Just in case, most boards have at least some memory */
#ifndef RAMSIZE
# define RAMSIZE (caddr_t)0x50000
#endif
/* Bitbanded Memory sections */
#define BITBAND_SRAM_REF 0x20000000
#define BITBAND_SRAM_BASE 0x22000000
#define BITBAND_PERI_REF 0x40000000
#define BITBAND_PERI_BASE 0x42000000
#endif
6) Add this codeblock to hardware->leaflabs->cores->maple->boards.h
#elif defined(BOARD_maple_discovery)
/* ST Microelectronics STMVLDISCOVERY evaluation board*/
#define CYCLES_PER_MICROSECOND 24
#define SYSTICK_RELOAD_VAL 23999 /* takes a cycle to reload */
#define BOARD_BUTTON_PIN 0 //compiler complains if not defined here...
#define BOARD_LED_PIN 40 //compiler complains if not defined here...
// TODO:
static __attribute__ ((unused)) PinMapping PIN_MAP[NR_GPIO_PINS] = {
{GPIOA_BASE, 0, ADC0, TIMER2_CH1_CCR, EXTI_CONFIG_PORTA, TIMER2, 1}, /* D0 PA0 3V only (User Button) */
{GPIOA_BASE, 1, ADC1, TIMER2_CH2_CCR, EXTI_CONFIG_PORTA, TIMER2, 2}, /* D1 PA1 3V only */
{GPIOA_BASE, 2, ADC2, TIMER2_CH3_CCR, EXTI_CONFIG_PORTA, TIMER2, 3}, /* D2 PA2 3V only */
{GPIOA_BASE, 3, ADC3, TIMER2_CH4_CCR, EXTI_CONFIG_PORTA, TIMER2, 4}, /* D3 PA3 3V only */
{GPIOA_BASE, 4, ADC4, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID}, /* D4 PA4 3V only */
{GPIOA_BASE, 5, ADC5, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID}, /* D5 PA5 3V only */
{GPIOA_BASE, 6, ADC6, TIMER3_CH1_CCR, EXTI_CONFIG_PORTA, TIMER3, 1}, /* D6 PA6 3V only */
{GPIOA_BASE, 7, ADC7, TIMER3_CH2_CCR, EXTI_CONFIG_PORTA, TIMER3, 2}, /* D7 PA7 3V only */
{GPIOA_BASE, 8, ADC_INVALID, TIMER1_CH1_CCR, EXTI_CONFIG_PORTA, TIMER1, 1}, /* D8 PA8 5V tolerant */
{GPIOA_BASE, 9, ADC_INVALID, TIMER1_CH2_CCR, EXTI_CONFIG_PORTA, TIMER1, 2}, /* D9 PA9 5V tolerant */
{GPIOA_BASE, 10, ADC_INVALID, TIMER1_CH3_CCR, EXTI_CONFIG_PORTA, TIMER1, 3}, /* D10 PA10 5V tolerant */
{GPIOA_BASE, 11, ADC_INVALID, TIMER1_CH4_CCR, EXTI_CONFIG_PORTA, TIMER1, 4}, /* D11 PA11 5V tolerant */
{GPIOA_BASE, 12, ADC_INVALID, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID}, /* D12 PA12 5V tolerant */
{GPIOA_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID}, /* D13 PA13 5V tolerant */
{GPIOA_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID}, /* D14 PA14 5V tolerant */
{GPIOA_BASE, 15, ADC_INVALID, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID}, /* D15 PA15 5V tolerant */
{GPIOB_BASE, 0, ADC8, TIMER3_CH3_CCR, EXTI_CONFIG_PORTB, TIMER3, 3}, /* D16 PB0 3V only */
{GPIOB_BASE, 1, ADC9, TIMER3_CH4_CCR, EXTI_CONFIG_PORTB, TIMER3, 4}, /* D17 PB1 3V only */
{GPIOB_BASE, 2, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, /* D18 PB2 5V tolerant */
{GPIOB_BASE, 3, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, /* D19 PB3 5V tolerant */
{GPIOB_BASE, 4, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, /* D20 PB4 5V tolerant */
{GPIOB_BASE, 5, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, /* D21 PB5 3V only */
{GPIOB_BASE, 6, ADC_INVALID, TIMER4_CH1_CCR, EXTI_CONFIG_PORTB, TIMER4, 1}, /* D22 PB6 5V tolerant */
{GPIOB_BASE, 7, ADC_INVALID, TIMER4_CH2_CCR, EXTI_CONFIG_PORTB, TIMER4, 2}, /* D23 PB7 5V tolerant */
{GPIOB_BASE, 8, ADC_INVALID, TIMER4_CH3_CCR, EXTI_CONFIG_PORTB, TIMER4, 3}, /* D24 PB8 5V tolerant */
{GPIOB_BASE, 9, ADC_INVALID, TIMER4_CH4_CCR, EXTI_CONFIG_PORTB, TIMER4, 4}, /* D25 PB9 5V tolerant */
{GPIOB_BASE, 10, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, /* D26 PB10 5V tolerant */
{GPIOB_BASE, 11, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, /* D27 PB11 5V tolerant */
{GPIOB_BASE, 12, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, /* D28 PB12 5V tolerant */
{GPIOB_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, /* D29 PB13 5V tolerant */
{GPIOB_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, /* D30 PB14 5V tolerant */
{GPIOB_BASE, 15, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, /* D31 PB15 5V tolerant */
{GPIOC_BASE, 0, ADC10, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, /* D32 PC0 3V only */
{GPIOC_BASE, 1, ADC11, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, /* D33 PC1 3V only */
{GPIOC_BASE, 2, ADC12, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, /* D34 PC2 3V only */
{GPIOC_BASE, 3, ADC13, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, /* D35 PC3 3V only */
{GPIOC_BASE, 4, ADC14, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, /* D36 PC4 3V only */
{GPIOC_BASE, 5, ADC15, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, /* D37 PC5 3V only */
{GPIOC_BASE, 6, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, /* D38 PC6 5V tolerant */
{GPIOC_BASE, 7, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, /* D39 PC7 5V tolerant */
{GPIOC_BASE, 8, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, /* D40 PC8 5V tolerant (Blue LED) */
{GPIOC_BASE, 9, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, /* D41 PC9 5V tolerant (Green LED) */
{GPIOC_BASE, 10, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, /* D42 PC10 5V tolerant */
{GPIOC_BASE, 11, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, /* D43 PC11 5V tolerant */
{GPIOC_BASE, 12, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, /* D44 PC12 5V tolerant */
{GPIOC_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, /* D45 PC13 3V only */
{GPIOC_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, /* D46 PC14 3V only */
{GPIOC_BASE, 15, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, /* D47 PC15 3V only */
{GPIOD_BASE, 0, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID}, /* D48 PD0 5V tolerant */
{GPIOD_BASE, 1, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID}, /* D49 PD1 5V tolerant */
{GPIOD_BASE, 2, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID} /* D50 PD2 5V tolerant */
};
Here is a blinky program to try out in your new environment :-)
/*
BlinkyButton for the Discover board
Alternates the built-in leds on a one second interval, repeatedly...
Speed the blinking up when the button is pressed.
There may be up to a two second delay from when you press the button to
when the leds speed up. Getting rid of the delay would be a good use of an interrupt. :-)
The circuit:
* Built-in LEDs connected to PC8, PC9 on Discover board
Based on an orginal code by H. Barragan for the Wiring i/o board
Created 1 June 2005 for Arduino By David Cuartielles
Modified for Discover board 18 March 2011 By ridgebackred */
// constants won't change. They're used here to
// set pin numbers:
const int buttonPin= 0; // User button connected to PA0 digital pin 0
const int blueledPin = 40; // Blue LED connected to PC8 digital pin 40
const int greenledPin = 41; // Green LED connected to PC9 digital pin 41
// variables will change:
int buttonState = 0; // Variable for reading the pushbutton status
// The setup() method runs once, when the sketch starts
void setup() {
// initialize the I/O:
pinMode(buttonPin, INPUT);
pinMode(blueledPin, OUTPUT);
pinMode(greenledPin, OUTPUT);
}
// the loop() method runs over and over again,
// as long as the board has power
void loop()
{
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
if (buttonState == LOW){
digitalWrite(greenledPin, HIGH); // Set the LED on
digitalWrite(blueledPin, LOW); // Set the LED off
delay(665); // Wait for a second:Discover timer is 1/3 too slow
digitalWrite(greenledPin, LOW); // Set the LED off
digitalWrite(blueledPin, HIGH); // Set the LED on
delay(665); // Wait for a second:Discover timer is 1/3 too slow
}
if (buttonState == HIGH){
digitalWrite(greenledPin, HIGH); // Set the LED on
digitalWrite(blueledPin, LOW); // Set the LED off
delay(65); // Wait for .1 second:Discover timer is 1/3 too slow
digitalWrite(greenledPin, LOW); // Set the LED off
digitalWrite(blueledPin, HIGH); // Set the LED on
delay(65); // Wait for .1 second:Discover timer is 1/3 too slow
}
}
The usart.c clock speeds will need tweaking, and who knows what else I have broken hacking around... :-)
Good Luck!
!!!!!!!!!!!!!!WARNING!!!!!!!!!!!!!!!!!!
The above set-up has bricked my Discovery.
The STM32 ST-Link Utility won't connect to the target.
When holding the reset button and connecting, the ST-Link Utility complains about flash sectors being protected and readout protection activated.
When I release the reset button the connection is immediately dropped.
The previously loaded program continues to run in the target device.
Debricking ideas anyone?
From clive1 at the my.ST.com forum...
It is certainly possible to brick the VL Discovery board with an out of control application. The ST-LINK portion can't reset and gain control over the application processor. I added some break-out code to monitor the button on start-up, as I think the problem I saw was with a interrupt storm.
One possible resolution to the bricked VL might be to change the state of the Boot pin so it doesn't run the application.
Thanks clive1, it worked for me. Jump the Boot pin to 3V3 at power-up to keep the target program from running, and the ST-Link Utility connects.
May be you used SWD pin PA13 or PA14 in your code?
I think it safer to exclude them from pinmap table. As well as PD0 and PD1.
You must log in to post.