Skip to content

Commit

Permalink
Adds bootloader application for STM32-F091 (#587)
Browse files Browse the repository at this point in the history
* Adds F091 bootloader.

* Fixes bootloader hardware pinout.
Adds bootloader appentry pointer to interrupt vector table.
Adds rflash command.

* Renames the directory because the pinout is different actually.
  • Loading branch information
balazsracz authored Dec 14, 2021
1 parent f9aef24 commit f9926a0
Show file tree
Hide file tree
Showing 14 changed files with 1,151 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
APP_PATH ?= $(realpath ../..)
-include $(APP_PATH)/config.mk
-include local_config.mk

OPENMRNPATH ?= $(shell \
sh -c "if [ \"X`printenv OPENMRNPATH`\" != \"X\" ]; then printenv OPENMRNPATH; \
elif [ -d /opt/openmrn/src ]; then echo /opt/openmrn; \
elif [ -d ~/openmrn/src ]; then echo ~/openmrn; \
elif [ -d ../../../src ]; then echo ../../..; \
else echo OPENMRNPATH not found; fi" \
)

-include $(OPENMRNPATH)/etc/config.mk
LINKCORELIBS = -lopenlcb -lutils

include $(OPENMRNPATH)/etc/stm32cubef0.mk

CFLAGSEXTRA += -DSTM32F091xC
CXXFLAGSEXTRA += -DSTM32F091xC
SYSLIBRARIES += -lfreertos_drivers_stm32cubef091xc
OPENOCDARGS = -f board/st_nucleo_f0.cfg

export TARGET := bare.armv6m

include $(OPENMRNPATH)/etc/prog.mk

ifndef DEFAULT_ADDRESS
DEFAULT_ADDRESS=0xff
endif

include $(OPENMRNPATH)/etc/node_id.mk

SYSLIB_SUBDIRS=
OBJEXTRA=
LDFLAGSEXTRA += -nostartfiles

all: $(EXECUTABLE).bin

# How to use: make multibin ADDRESS=0x20 ADDRHIGH=0x45 NUM=3
# starting address, high bits (user range), count
multibin:
for i in $$(seq 1 $(NUM)) ; do $(MAKE) $(EXECUTABLE).bin ADDRESS=$$(printf 0x%02x $$(($(ADDRESS)+$$i))) ; cp $(EXECUTABLE).bin $(EXECUTABLE).$(MCU_SHORT).$$(printf %02x%02x $(ADDRHIGH) $$(($(ADDRESS)+$$i-1))).bin ; done

ifeq ($(call find_missing_deps,OPENOCDPATH OPENOCDSCRIPTSPATH),)

flash: $(EXECUTABLE)$(EXTENTION) $(EXECUTABLE).bin $(EXECUTABLE).lst
@if ps ax -o comm | grep -q openocd ; then echo openocd already running. quit existing first. ; exit 1 ; fi
$(GDB) $< -ex "target remote | $(OPENOCDPATH)/openocd -c \"gdb_port pipe\" --search $(OPENOCDSCRIPTSPATH) $(OPENOCDARGS)" -ex "monitor reset halt" -ex "load" -ex "monitor reset init" -ex "monitor reset run" -ex "detach" -ex "quit"

lflash: $(EXECUTABLE).bin $(EXECUTABLE).lst
@if ps ax -o comm | grep -q openocd ; then echo openocd already running. quit existing first. ; exit 1 ; fi
$(GDB) $< -ex "target remote | $(OPENOCDPATH)/openocd -c \"gdb_port pipe\" --search $(OPENOCDSCRIPTSPATH) $(OPENOCDARGS)" -ex "monitor reset halt" -ex "monitor program $< 0x08000000 verify reset exit" -ex "monitor reset run" -ex "detach" -ex "quit"

gdb:
@if ps ax -o comm | grep -q openocd ; then echo openocd already running. quit existing first. ; exit 1 ; fi
$(GDB) $(EXECUTABLE)$(EXTENTION) -ex "target remote | $(OPENOCDPATH)/openocd -c \"gdb_port pipe\" --search $(OPENOCDSCRIPTSPATH) $(OPENOCDARGS)" -ex "continue" # -ex "monitor reset halt"

else

flash gdb:
echo OPENOCD not found ; exit 1

endif

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include "openlcb/If.hxx"
#include "address.h"

#ifndef NODEID_HIGH_BITS
#define NODEID_HIGH_BITS 0x18
#endif

extern const openlcb::NodeID NODE_ID;
const openlcb::NodeID NODE_ID = 0x050101010000ULL | (NODEID_HIGH_BITS << 8) | NODEID_LOW_BITS;
extern const uint16_t DEFAULT_ALIAS;
const uint16_t DEFAULT_ALIAS = 0x400 | NODEID_LOW_BITS;

//#define BOOTLOADER_STREAM
//#define BOOTLOADER_DATAGRAM
//#include "openlcb/Bootloader.hxx"
182 changes: 182 additions & 0 deletions boards/st-stm32f091rc-nucleo/BootloaderHal.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
#include <string.h>

#define BOOTLOADER_STREAM
//#define BOOTLOADER_DATAGRAM

#include "BootloaderHal.hxx"
#include "bootloader_hal.h"

#include "nmranet_config.h"
#include "openlcb/Defs.hxx"
#include "Stm32Gpio.hxx"
#include "openlcb/Bootloader.hxx"
#include "openlcb/If.hxx"
#include "utils/GpioInitializer.hxx"

const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
const uint32_t HSEValue = 8000000;

int g_death_lineno = 0;

extern "C" {

GPIO_PIN(LED_GREEN, LedPin, A, 5);
GPIO_PIN(SW1, GpioInputPU, C, 13);

static constexpr unsigned clock_hz = 48000000;

void bootloader_hw_set_to_safe(void)
{
SW1_Pin::hw_set_to_safe();
LED_GREEN_Pin::hw_set_to_safe();
}

extern void bootloader_reset_segments(void);
//extern unsigned long cm3_cpu_clock_hz;

/** Setup the system clock */
static void clock_setup(void)
{
/* reset clock configuration to default state */
RCC->CR = RCC_CR_HSITRIM_4 | RCC_CR_HSION;
while (!(RCC->CR & RCC_CR_HSIRDY))
;

#define USE_EXTERNAL_8_MHz_CLOCK_SOURCE 1
/* configure PLL: 8 MHz * 6 = 48 MHz */
#if USE_EXTERNAL_8_MHz_CLOCK_SOURCE
RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP;
while (!(RCC->CR & RCC_CR_HSERDY))
;
RCC->CFGR = RCC_CFGR_PLLMUL6 | RCC_CFGR_PLLSRC_HSE_PREDIV | RCC_CFGR_SW_HSE;
while (!((RCC->CFGR & RCC_CFGR_SWS) == RCC_CFGR_SWS_HSE))
;
#else
RCC->CFGR = RCC_CFGR_PLLMUL6 | RCC_CFGR_PLLSRC_HSI_PREDIV | RCC_CFGR_SW_HSI;
while (!((RCC->CFGR & RCC_CFGR_SWS) == RCC_CFGR_SWS_HSI))
;
#endif
/* enable PLL */
RCC->CR |= RCC_CR_PLLON;
while (!(RCC->CR & RCC_CR_PLLRDY))
;

/* set PLL as system clock */
RCC->CFGR = (RCC->CFGR & (~RCC_CFGR_SW)) | RCC_CFGR_SW_PLL;
while (!((RCC->CFGR & RCC_CFGR_SWS) == RCC_CFGR_SWS_PLL))
;
}

void bootloader_hw_init()
{
/* Globally disables interrupts until the FreeRTOS scheduler is up. */
asm("cpsid i\n");

/* these FLASH settings enable opertion at 48 MHz */
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
__HAL_FLASH_SET_LATENCY(FLASH_LATENCY_1);

/* Reset HSI14 bit */
RCC->CR2 &= (uint32_t)0xFFFFFFFEU;

/* Disable all interrupts */
RCC->CIR = 0x00000000U;

clock_setup();

/* enable peripheral clocks */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_CAN1_CLK_ENABLE();

/* setup pinmux */
GPIO_InitTypeDef gpio_init;
memset(&gpio_init, 0, sizeof(gpio_init));

/* CAN pinmux on PB8 and PB9 */
gpio_init.Mode = GPIO_MODE_AF_PP;
// Disables pull-ups because this is a 5V tolerant pin.
gpio_init.Pull = GPIO_NOPULL;
gpio_init.Speed = GPIO_SPEED_FREQ_HIGH;
gpio_init.Alternate = GPIO_AF4_CAN;
gpio_init.Pin = GPIO_PIN_8;
HAL_GPIO_Init(GPIOB, &gpio_init);
gpio_init.Pin = GPIO_PIN_9;
HAL_GPIO_Init(GPIOB, &gpio_init);

LED_GREEN_Pin::hw_init();
SW1_Pin::hw_init();

/* disable sleep, enter init mode */
CAN->MCR = CAN_MCR_INRQ;

/* Time triggered tranmission off
* Bus off state is left automatically
* Auto-Wakeup mode disabled
* automatic re-transmission enabled
* receive FIFO not locked on overrun
* TX FIFO mode on
*/
CAN->MCR |= (CAN_MCR_ABOM | CAN_MCR_TXFP);

/* Setup timing.
* 125,000 Kbps = 8 usec/bit
*/
CAN->BTR = (CAN_BS1_5TQ | CAN_BS2_2TQ | CAN_SJW_1TQ |
((clock_hz / 1000000) - 1));

/* enter normal mode */
CAN->MCR &= ~CAN_MCR_INRQ;

/* Enter filter initialization mode. Filter 0 will be used as a single
* 32-bit filter, ID Mask Mode, we accept everything, no mask.
*/
CAN->FMR |= CAN_FMR_FINIT;
CAN->FM1R = 0;
CAN->FS1R = 0x000000001;
CAN->FFA1R = 0;
CAN->sFilterRegister[0].FR1 = 0;
CAN->sFilterRegister[0].FR2 = 0;

/* Activeate filter and exit initialization mode. */
CAN->FA1R = 0x000000001;
CAN->FMR &= ~CAN_FMR_FINIT;
}

void bootloader_led(enum BootloaderLed id, bool value)
{
switch(id)
{
case LED_ACTIVE:
LED_GREEN_Pin::set(value);
return;
case LED_WRITING:
LED_GREEN_Pin::set(value);
return;
case LED_CSUM_ERROR:
return;
case LED_REQUEST:
return;
case LED_FRAME_LOST:
return;
default:
/* ignore */
break;
}
}

bool request_bootloader()
{
extern uint32_t __bootloader_magic_ptr;
if (__bootloader_magic_ptr == REQUEST_BOOTLOADER) {
__bootloader_magic_ptr = 0;
LED_GREEN_Pin::set(true);
return true;
}
LED_GREEN_Pin::set(SW1_Pin::get());
return !SW1_Pin::get();
}

} // extern "C"
6 changes: 6 additions & 0 deletions boards/st-stm32f091rc-nucleo/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,9 @@ flash gdb:
echo OPENOCD not found ; exit 1

endif

BLOAD_HOST ?= localhost

rflash: $(EXECUTABLE).bin
$(OPENMRNPATH)/applications/bootloader_client/targets/linux.x86/bootloader_client -w 100 -W 100 -c tiva123 -i $(BLOAD_HOST) -r -n 0x0501010118$$(printf %02x $(ADDRESS)) -f $(EXECUTABLE).bin
cp -f $(EXECUTABLE)$(EXTENTION) $(EXECUTABLE)-$$(printf %02x $(ADDRESS))$(EXTENTION)
9 changes: 8 additions & 1 deletion boards/st-stm32f091rc-nucleo/memory_map.ld
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
___ram_for_bootloader_api = 8;

MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 240K
EEPROMEMU (r) : ORIGIN = 0x0803C000, LENGTH = 8K
BOOTLOADER (rx) : ORIGIN = 0x0803E000, LENGTH = 8K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 32K
RAM (rwx) : ORIGIN = 0x20000000,
LENGTH = 32K - ___ram_for_bootloader_api
BOOTLOADERAPI (rw) : ORIGIN = 0x20000000 + 32K - ___ram_for_bootloader_api,
LENGTH = ___ram_for_bootloader_api
}

__flash_start = ORIGIN(FLASH);
Expand All @@ -12,4 +17,6 @@ __eeprom_start = ORIGIN(EEPROMEMU);
__eeprom_end = ORIGIN(EEPROMEMU) + LENGTH(EEPROMEMU);
__bootloader_start = ORIGIN(BOOTLOADER);
__app_header_offset = 0x270;
__app_header_address = ORIGIN(FLASH) + __app_header_offset;
__bootloader_magic_ptr = ORIGIN(RAM);
__application_node_id = ORIGIN(BOOTLOADERAPI);
Loading

0 comments on commit f9926a0

Please sign in to comment.