PREFIX = /usr/local ARCH = arm-none-eabi BINDIR = $(PREFIX)/$(ARCH)/bin ADDNAME = $(ARCH)- AR = $(BINDIR)/$(ADDNAME)ar AS = $(BINDIR)/$(ADDNAME)as CC = $(BINDIR)/$(ADDNAME)gcc LD = $(BINDIR)/$(ADDNAME)ld NM = $(BINDIR)/$(ADDNAME)nm OBJCOPY = $(BINDIR)/$(ADDNAME)objcopy OBJDUMP = $(BINDIR)/$(ADDNAME)objdump RANLIB = $(BINDIR)/$(ADDNAME)ranlib STRIP = $(BINDIR)/$(ADDNAME)strip OBJS += reset.o main.o OBJS += vector.o TARGET = xiao CFLAGS = -Wall -mcpu=cortex-m0 -mthumb -nostdinc -nostdlib -fno-builtin CFLAGS += -I. #CFLAGS += -g CFLAGS += -Os CFLAGS += -DXIAO CFLAGS += -DCPU_CLOCK=12000000L LFLAGS = -static -T ld.scr -L. .SUFFIXES: .c .o .SUFFIXES: .s .o .SUFFIXES: .S .o all : $(TARGET) $(TARGET) : $(OBJS) $(CC) $(OBJS) -o $(TARGET) $(CFLAGS) $(LFLAGS) cp $(TARGET) $(TARGET).elf $(STRIP) $(TARGET) .c.o : $< $(CC) -c $(CFLAGS) $< .s.o : $< $(CC) -c $(CFLAGS) $< .S.o : $< $(CC) -c $(CFLAGS) $< $(TARGET).mot : $(TARGET) $(OBJCOPY) -O srec $(TARGET) $(TARGET).mot $(TARGET).hex : $(TARGET).mot $(OBJCOPY) -I srec -O ihex $(TARGET).mot $(TARGET).hex image : $(TARGET).hex lpc21isp xiao.hex /dev/ttyUSB0 115200 12000 clean : rm -f $(OBJS) $(TARGET) $(TARGET).elf $(TARGET).mot $(TARGET).hex rm -f *~
第2世代 Xiaoの検討 最低限のソースコード
| 作成日 | : | 2020/07/12 |
|---|---|---|
| 最終更新日 | : | 2020/07/13 |
第2世代 Xiaoの検討 最低限のソースコード
| 作成日 | : | 2020/07/12 |
|---|---|---|
| 最終更新日 | : | 2020/07/13 |
概要
第2世代 Xiaoは第1世代のXiaoとの互換性は考えない予定です。 しかしながら、再利用できる部分は使いたいので一旦main関数を呼び出すところまで簡略化します。
開発環境
開発環境はGNUツールチェーンを使用します。GNU makeを使ってビルドを自動化します。
ソース1. Makefile
ソースコード
リンカスクリプトはXiaoのものをとりあえずそのまま利用します。リンカスクリプトのファイル名は12ステップ本を踏襲します。
ソース2. ld.scr
OUTPUT_FORMAT("elf32-littlearm")
OUTPUT_ARCH(arm)
MEMORY
{
romall(rx) : o = 0x00000000, l = 0x00008000 /* 16KB */
romvector(r) : o = 0x00000000, l = 0x00000200 /* top of ROM */
rom(rx) : o = 0x00000200, l = 0x00007e00
ramall(rwx) : o = 0x10000000, l = 0x00001000 /* 4KB */
data(rw) : o = 0x10000000, l = 0x00000800 /* 2KB */
userstack(rw) : o = 0x10000800, l = 0x00000400 /* 1KB */
stack(rw) : o = 0x10000C00, l = 0x00000400 /* end of RAM */
}
SECTIONS
{
.romvector : {
_romvector_start = . ;
*(.vector)
. = ALIGN(4);
_romvector_end = . ;
} > romvector
.text : {
_text_start = . ;
*(.text)
_etext = . ;
} > rom
.rodata : {
_rodata_start = . ;
*(.strings)
*(.rodata)
*(.rodata.*)
_erodata = . ;
} > rom
_data_org = . ;
.data : {
_data_start = . ;
*(.data)
. = ALIGN(4);
_data_end = . ;
_edata = . ;
} > data AT> rom
.bss : {
_bss_start = . ;
*(.bss)
*(COMMON)
. = ALIGN(4);
_bss_end = . ;
_ebss = . ;
} > data AT> rom
. = ALIGN(4);
_end = . ;
.freearea : {
_freearea = . ;
} > data
.userstack : {
_userstack = . ;
} > userstack
.stack : {
_process_stack = . + 0x0100;
_main_stack = . + 0x0200;
} > stack
}必要な定義は一旦defines.hにまとめます。追々ファイルを整理していきます。
ソース3. defines.h
/** defines.h Copyright (c) 2013-2020 Akihisa ONODA This software is released under the MIT License. http://opensource.org/licenses/mit-license.php */ #ifndef __DEFINES_H__ #define __DEFINES_H__ #define NULL ((void *)0) #define SYSMEMREMAP ((volatile unsigned long *)0x40048000) #define SYSAHBCLKCTRL ((volatile unsigned long *)0x40048080) #define AHB_IOCON (1 << 16) #endif /* __DEFINES_H__ */
電源投入された時、一番初めにvector.cに定義したvectorの0番目にスタックポインタのアドレスを定義し、1番目のアドレスに飛びます。ここでアドレスに+1しているのはARM Cortex-M0の仕様です。ブートストラップ処理を書いていきます。LPC1114FN28/102はRAMが4 kbyteと少ないので第1世代のXiao同様にブートローダは実装せずに直接ブートする仕様にします。
ソース4. vector.c
/**
vecter.c
Copyright (c) 2013-2020 Akihisa ONODA
This software is released under the MIT License.
http://opensource.org/licenses/mit-license.php
*/
extern unsigned long _main_stack[];
void reset_entry(void);
const void *vector[] __attribute__ ((section(".romvector"))) =
{
_main_stack, // MSP
reset_entry + 1, // 1: Reset
reset_entry + 1, // 2: NMI
reset_entry + 1, // 3: HardFault
reset_entry + 1, // 4: reserved
reset_entry + 1, // 5: reserved
reset_entry + 1, // 6: reserved
reset_entry + 1, // 7: reserved
reset_entry + 1, // 8: reserved
reset_entry + 1, // 9: reserved
reset_entry + 1, // 10: reserved
reset_entry + 1, // 11: SVC
reset_entry + 1, // 12: reserved
reset_entry + 1, // 13: reserved
reset_entry + 1, // 14: PendSV
reset_entry + 1, // 15: SysTick
reset_entry + 1, // 16: External Interrupt PIO0_0
reset_entry + 1, // 17: External Interrupt PIO0_1
reset_entry + 1, // 18: External Interrupt PIO0_2
reset_entry + 1, // 19: External Interrupt PIO0_3
reset_entry + 1, // 20: External Interrupt PIO0_4
reset_entry + 1, // 21: External Interrupt PIO0_5
reset_entry + 1, // 22: External Interrupt PIO0_6
reset_entry + 1, // 23: External Interrupt PIO0_7
reset_entry + 1, // 24: External Interrupt PIO0_8
reset_entry + 1, // 25: External Interrupt PIO0_9
reset_entry + 1, // 26: External Interrupt PIO0_10
reset_entry + 1, // 27: External Interrupt PIO0_11
reset_entry + 1, // 28: External Interrupt PIO1_10
reset_entry + 1, // 29: External Interrupt C_CAN
reset_entry + 1, // 30: External Interrupt SPC/SSP1
reset_entry + 1, // 31: External Interrupt I2C0
reset_entry + 1, // 32: External Interrupt
reset_entry + 1, // 33: External Interrupt
reset_entry + 1, // 34: External Interrupt
reset_entry + 1, // 35: External Interrupt
reset_entry + 1, // 36: External Interrupt
reset_entry + 1, // 37: External Interrupt
reset_entry + 1, // 38: External Interrupt
reset_entry + 1, // 39: External Interrupt
reset_entry + 1, // 40: External Interrupt
reset_entry + 1, // 41: External Interrupt
reset_entry + 1, // 42: External Interrupt
reset_entry + 1, // 43: External Interrupt
reset_entry + 1, // 44: External Interrupt
reset_entry + 1, // 45: External Interrupt
reset_entry + 1, // 46: External Interrupt
reset_entry + 1, // 47: External Interrupt
reset_entry + 1, // 48: External Interrupt
reset_entry + 1, // 49: External Interrupt
reset_entry + 1, // 50: External Interrupt
reset_entry + 1, // 51: External Interrupt
reset_entry + 1, // 52: External Interrupt
reset_entry + 1, // 53: External Interrupt
reset_entry + 1, // 54: External Interrupt
reset_entry + 1, // 55: External Interrupt
reset_entry + 1, // 56: External Interrupt
reset_entry + 1, // 57: External Interrupt
reset_entry + 1, // 58: External Interrupt
reset_entry + 1, // 59: External Interrupt
reset_entry + 1, // 60: External Interrupt
reset_entry + 1, // 61: External Interrupt
reset_entry + 1, // 62: External Interrupt
reset_entry + 1, // 63: External Interrupt
};今回は、reset_entryに飛ぶようにしているので、reset.cに定義されたreset_entry()が呼び出されます。アセンブラはインラインアセンブラでできるだけ記述するようにし、*.cファイルで済むようにします。
ソース5. reset.c
/**
reset.c
Copyright (c) 2013-2020 Akihisa ONODA
This software is released under the MIT License.
http://opensource.org/licenses/mit-license.php
*/
#include "defines.h"
__attribute__ ((section(".text.startup")))
void
reset_entry(void)
{
extern volatile char _data_org[], _data_start[], _data_end[];
extern volatile char _bss_start[], _bss_end[];
volatile char *s, *d;
asm("ldr r0, =_process_stack\n"
"msr psp, r0\n");
asm("mov r0, #2\n"
"msr control, r0\n");
asm("memmap_init:\n");
*SYSMEMREMAP = 2;
asm("clock_init:\n");
*SYSAHBCLKCTRL |= AHB_IOCON;
for(d = _data_start, s = _data_org; d < _data_end; *d++ = *s++);
for(d = _bss_start; d < _bss_end; *d++ = 0);
asm("b main\n");
}reset_entry()の最後でmain.cに定義されたmain()を呼び出してブートストラップが完了します。
ソース6. main.c
/**
main.c
Copyright (c) 2013-2020 Akihisa ONODA
This software is released under the MIT License.
http://opensource.org/licenses/mit-license.php
*/
#include "defines.h"
int
main(void)
{
return 0;
}