はじめに
前回は、wolfBootを使うための環境を整えました。
今回は、NUCLEO-F401REでwolfBootを動かすための準備を行いました。
使用機器
- Windows11
- WSL2
- Ubuntu
手順
コンフィグレーションファイルの準備
STM32F401用のmakeで使用する設定ファイルになります。
コンフィグレーションファイルは、ファイル名を .config としてルートディレクトリにおきます。
コンフィグレーションファイルは、STM32F4用のものを基にして作成します。
ルートディレクトリにコピーします。
wolfBoot$> cp ./config/examples/stm32f4.config .config
STM32F4用のコンフィグレーションファイルをコピーしたので、STM32F401用とするために以下の変更を行います。
(変更前)
TARGET?=stm32f4
(変更後)
TARGET?=stm32f401
機種依存ファイルの準備
機種ごとに必要となるペリフェラルのドライバとリンカスクリプトファイルをコピーします。
こちらもSTM32F4用のものを基にして作成します。
wolfBoot$> cd hal
wolfBoot/hal$> cp ./stm32f4.c ./stm32f401.c
wolfBoot/hal$> cp ./stm32f4.ld ./stm32f401.ld
stm32f401.cは、STM32F4用のファイルを基にしているためSTM32F401用に変更します。
ファイルの上から順に下記のように変更しました。
// 変更点のみの抜粋となります。
// 変更をする際に、STM32F401のリファレンスマニュアル(RM0368)を参照します。
// stm32f4.cでは、PLLのソースクロックを外部発振子とする設定になっていますが、
// NUCLEO-F401REにはデフォルトで外部発振子は未実装のためPLLのソースクロックを
// 内臓のHSIオシレータクロックとします。
// RM0368 P.105 6.3.2章より
#define RCC_PLLCFGR_PLLSRC (0 << 22) //(1 << 22)
// STM32F401REの動作周波数は84MHzとなるので分周比を修正します。
#define RCC_PRESCALER_DIV_2 4 //8
// 内蔵フラッシュのセクタの定義を修正します。
// RM0368 P.45 3.3章より
/* FLASH Geometry */
#define FLASH_SECTOR_0 0x0000000 /* 16 Kb */
#define FLASH_SECTOR_1 0x0004000 /* 16 Kb */
#define FLASH_SECTOR_2 0x0008000 /* 16 Kb */
#define FLASH_SECTOR_3 0x000C000 /* 16 Kb */
#define FLASH_SECTOR_4 0x0010000 /* 64 Kb */
#define FLASH_SECTOR_5 0x0020000 /* 128 Kb */
#define FLASH_SECTOR_6 0x0040000 /* 128 Kb */
#define FLASH_SECTOR_7 0x0060000 /* 128 Kb */
//#define FLASH_SECTOR_8 0x0080000 /* 128 Kb */
//#define FLASH_SECTOR_9 0x00A0000 /* 128 Kb */
//#define FLASH_SECTOR_10 0x00C0000 /* 128 Kb */
//#define FLASH_SECTOR_11 0x00E0000 /* 128 Kb */
#define FLASH_TOP 0x0100000
//#define FLASH_SECTORS 12
#define FLASH_SECTORS 8
const uint32_t flash_sector[FLASH_SECTORS + 1] = {
FLASH_SECTOR_0,
FLASH_SECTOR_1,
FLASH_SECTOR_2,
FLASH_SECTOR_3,
FLASH_SECTOR_4,
FLASH_SECTOR_5,
FLASH_SECTOR_6,
FLASH_SECTOR_7,
//FLASH_SECTOR_8,
//FLASH_SECTOR_9,
//FLASH_SECTOR_10,
//FLASH_SECTOR_11,
FLASH_TOP
};
// stm32f4.cでは外部発振子を使用していますが、NUCLEO-F401REにはデフォルトで外部発振子は未実装のため
// クロックは内臓のHSIオシレータクロックを使用します。
static void clock_pll_on(int powersave)
{
uint32_t reg32;
uint32_t cpu_freq, plln, pllm, pllq, pllp, pllr, hpre, ppre1, ppre2, flash_waitstates;
/* Enable Power controller */
APB1_CLOCK_ER |= PWR_APB1_CLOCK_ER_VAL;
// HSIオシレータクロックを使用して84MHzで動作させるためにクロックの設定を見直します。
/* Select clock parameters (CPU Speed = 84MHz) */
cpu_freq = 84000000; (void)cpu_freq; /* not used */
pllm = 16; //8
plln = 336;
pllp = 4; //2
pllq = 7;
pllr = 0; (void)pllr; /* not used */
hpre = RCC_PRESCALER_DIV_NONE;
ppre1 = RCC_PRESCALER_DIV_2; //RCC_PRESCALER_DIV_4;
ppre2 = RCC_PRESCALER_DIV_NONE; //RCC_PRESCALER_DIV_2;
flash_waitstates = 3;
flash_set_waitstates(flash_waitstates);
/* Enable internal high-speed oscillator. */
RCC_CR |= RCC_CR_HSION;
DMB();
while ((RCC_CR & RCC_CR_HSIRDY) == 0) {};
/* Select HSI as SYSCLK source. */
reg32 = RCC_CFGR;
reg32 &= ~((1 << 1) | (1 << 0));
RCC_CFGR = (reg32 | RCC_CFGR_SW_HSI);
DMB();
#if 0
外部発振子を有効にしていますが、NUCLEO-STM32F401REには外部発信子はデフォルトで未実装のため本処理は無効とします。
RM0638 P.103 6.3.1章より
/* Enable external high-speed oscillator 8MHz. */
RCC_CR |= RCC_CR_HSEON;
DMB();
while ((RCC_CR & RCC_CR_HSERDY) == 0) {};
#endif
/*
* Set prescalers for AHB, ADC, ABP1, ABP2.
*/
reg32 = RCC_CFGR;
reg32 &= ~(0xF0);
RCC_CFGR = (reg32 | (hpre << 4));
DMB();
reg32 = RCC_CFGR;
reg32 &= ~(0x1C00);
RCC_CFGR = (reg32 | (ppre1 << 10));
DMB();
reg32 = RCC_CFGR;
reg32 &= ~(0x07 << 13);
RCC_CFGR = (reg32 | (ppre2 << 13));
DMB();
/* Set PLL config */
reg32 = RCC_PLLCFGR;
reg32 &= ~(PLL_FULL_MASK);
RCC_PLLCFGR = reg32 | RCC_PLLCFGR_PLLSRC | pllm |
(plln << 6) | (((pllp >> 1) - 1) << 16) |
(pllq << 24);
DMB();
/* Enable PLL oscillator and wait for it to stabilize. */
RCC_CR |= RCC_CR_PLLON;
DMB();
while ((RCC_CR & RCC_CR_PLLRDY) == 0) {};
/* Select PLL as SYSCLK source. */
reg32 = RCC_CFGR;
reg32 &= ~((1 << 1) | (1 << 0));
RCC_CFGR = (reg32 | RCC_CFGR_SW_PLL);
DMB();
/* Wait for PLL clock to be selected. */
while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SW_PLL) {};
#if 0
stm32f4.cでは、外部発信子を使用するためにHSIオシレータクロックを停止していますが、
NUCLEO-STM32F401REでは、HSIオシレータクロックを使用するために本処理は無効とします。
RM0368 P.103 6.3.1章より
/* Disable internal high-speed oscillator. */
RCC_CR &= ~RCC_CR_HSION;
#endif
}
リンカスクリプトファイルを変更します。
/* 変更点のみの抜粋となります */
/* stm32f.ldを基にしているためSTM32F401に合わせてRAMサイズを変更します */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = @BOOTLOADER_PARTITION_SIZE@
/*RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x0001C000*/
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00018000
}
テスト用のアプリケーションの準備
テスト用のアプリケーションファイルを準備します。
こちらもSTM32F4用のものを基にして作成します。
wolfBoot$> cd test-app
wolfBoot/test-app$> cp ./stm32f4.c ./stm32f401.c
各種ファイルの修正
/wolfBoot/test-app内の各種ファイルにある条件付きコンパイルの判定条件を変更します。
STM32F401向けの関数が不足してmakeでエラーとなるため、条件付きコンパイルの判定条件を修正しました。
本来であれば、STM32F401の関数を準備するほうがいいと思います。
// 変更点のみの抜粋となります。
//#if defined(PLATFORM_stm32f4) || defined(PLATFORM_stm32f7)
#if defined(PLATFORM_stm32f4) || defined(PLATFORM_stmf401) || defined(PLATFORM_stm32f7)
// 新規追加
/* STM32F401, 84 MHz */
#ifdef PLATFORM_stm32f401
# define PLLM 8
# define PLLN 336
# define PLLP 2
# define PLLQ 7
# define PLLR 0
# define TARGET_FLASH_WAITSTATES 5
#endif
// 変更点のみの抜粋となります。
//#ifdef PLATFORM_stm32f4
#if defined(PLATFORM_stm32f4) || defined(PLATFORM_stm32f401)
// 変更点のみの抜粋となります。
//#ifdef PLATFORM_stm32f4
#if defined(PLATFORM_stm32f4) || defined(PLATFORM_stm32f401)
makeファイルの修正
factory.binを作成するときに使用されるオフセット値を修正します。
ifreq ($(TARGET),stm32f4)
ARCH_FLASH_OFFSET=0x08000000
SPI_TARGET=stm32
endif
# 追加します。
ifreq ($(TARGET),stm32f401)
ARCH_FLASH_OFFSET=0x08000000
SPI_TARGET=stm32
endif
ARCH_FLASH_OFFSETは、wolfboot.binとimage_v1_signed.binをfactory.binにまとめるときに使用されるようです。
ARCH_FLASH_OFFSETを定義しないとデフォルト値は0(ゼロ)のようで、ゼロ番地にwolfboot.binを割り当てたfactory.binが作成されます。
make
STM32F401向けの対応が完了したらmakeします。
wolfBoot$> make clean
wolfBoot$> make
下記のファイルが作成されれば準備は完了となります。
- wolfBoot/wolfboot.elf
- wolfBoot/factory.bin
- wolfBoot/hal/stm32f401.o
- wolfBoot/test-app/image.elf
編集後記
wolfBootをNUCLEO-F401REで動作させるために下記のファイル
- /wolfBoot/test-app/system.c
- /wolfBoot/test-app/led.c
- /wolfBoot/test-app/test.c
についてはmakeでエラーとならいないようにするための対応のみ行いました。
必要なときが来たらちゃんと対応してみたいと思います。
次回は、STM32CubeIDEを使用して、wolfBootをNUCLEO-STM32F401で動作させたいと思います。