1.前言
让我们先来了解一下cortex-m3和stm32、lm3s之间的关系。arm是一家只设计cpu的公司,所以会授权硬件公司开发具体的处理器,arm设计的是处理器的核心部件,之后的一些核心外围的部件由具体的硬件公司自己添加(按约定的规则),arm设计了cortex-m的架构,而cortex-m3是一个型号的内核,stm32是意法半导体基于cortex-m设计的一系列具体的微控制器。lm3s与之类似,lm3s之前的公司现在已经被TI(德州仪器)收购。
嵌入式微控制器涉及软硬件设计,初学者一般先用现成的开发板学习基本知识。软件开发就涉及一个编译器的问题,cortex-m3的开发有很多工具,著名的由ARMCC(arm公司自己开发的工具),keil(学过51单片机的同学应该会知道),gcc。这里我个人偏向于使用gcc,所以在这里会说明如何编译gcc。
硬件我先使用了qemu模拟器模拟的一块cortex-m3开发板(lm3s6965evb),用于学习cortex-m3的基础知识。
2.构建gcc和qemu(操作系统为linux)
现从网上下载binutils2.24,gcc4.9.1,newlib-nano1.0,qemu2.1,gdb7.7源代码。
binutils配置(一般我们会建立一个文件夹用于编译,而不在源代码目录编译):
../binutils-2.24/configure --target=arm-none-eabi \ --prefix=/opt/cross-cortex-m3 \ //指定路径 --with-sysroot=/opt/cross-cortex-m3/arm-none-eabi \ --enable-nls --enable-gold \ --enable-plugins --enable-lto --disable-werror \ --enable-multilib --enable-interwork
编译安装
make -j8 make install(我用的是ubuntu所以需要前面加sudo)
gcc配置(libgmp,libmpfr,libmpc, libzip)(打补丁patch -N ${GCC_VERSION}/gcc/config/arm/t-arm-elf gcc-multilib.patch):
--- t-arm-elf.orig 2012-09-09 21:18:49.000000000 +0200 +++ gcc-linaro-4.7-2012.08/gcc/config/arm/t-arm-elf 2012-09-11 17:00:04.000000000 +0200 @@ -17,75 +17,29 @@ # along with GCC; see the file COPYING3. If not see # <http://www.gnu.org/licenses/>. -MULTILIB_OPTIONS = marm/mthumb -MULTILIB_DIRNAMES = arm thumb -MULTILIB_EXCEPTIONS = -MULTILIB_MATCHES = - -#MULTILIB_OPTIONS += mcpu=fa526/mcpu=fa626/mcpu=fa606te/mcpu=fa626te/mcpu=fmp626/mcpu=fa726te -#MULTILIB_DIRNAMES += fa526 fa626 fa606te fa626te fmp626 fa726te -#MULTILIB_EXCEPTIONS += *mthumb*/*mcpu=fa526 *mthumb*/*mcpu=fa626 - -#MULTILIB_OPTIONS += march=armv7 -#MULTILIB_DIRNAMES += thumb2 -#MULTILIB_EXCEPTIONS += march=armv7* marm/*march=armv7* -#MULTILIB_MATCHES += march?armv7=march?armv7-a -#MULTILIB_MATCHES += march?armv7=march?armv7-r -#MULTILIB_MATCHES += march?armv7=march?armv7-m -#MULTILIB_MATCHES += march?armv7=mcpu?cortex-a8 -#MULTILIB_MATCHES += march?armv7=mcpu?cortex-r4 -#MULTILIB_MATCHES += march?armv7=mcpu?cortex-m3 - -# Not quite true. We can support hard-vfp calling in Thumb2, but how do we -# express that here? Also, we really need architecture v5e or later -# (mcrr etc). -MULTILIB_OPTIONS += mfloat-abi=hard -MULTILIB_DIRNAMES += fpu -MULTILIB_EXCEPTIONS += *mthumb/*mfloat-abi=hard* -#MULTILIB_EXCEPTIONS += *mcpu=fa526/*mfloat-abi=hard* -#MULTILIB_EXCEPTIONS += *mcpu=fa626/*mfloat-abi=hard* - -# MULTILIB_OPTIONS += mcpu=ep9312 -# MULTILIB_DIRNAMES += ep9312 -# MULTILIB_EXCEPTIONS += *mthumb/*mcpu=ep9312* -# -# MULTILIB_OPTIONS += mlittle-endian/mbig-endian -# MULTILIB_DIRNAMES += le be -# MULTILIB_MATCHES += mbig-endian=mbe mlittle-endian=mle -# -# MULTILIB_OPTIONS += mfloat-abi=hard/mfloat-abi=soft -# MULTILIB_DIRNAMES += fpu soft -# MULTILIB_EXCEPTIONS += *mthumb/*mfloat-abi=hard* -# -# MULTILIB_OPTIONS += mno-thumb-interwork/mthumb-interwork -# MULTILIB_DIRNAMES += normal interwork -# -# MULTILIB_OPTIONS += fno-leading-underscore/fleading-underscore -# MULTILIB_DIRNAMES += elf under -# -# MULTILIB_OPTIONS += mcpu=arm7 -# MULTILIB_DIRNAMES += nofmult -# MULTILIB_EXCEPTIONS += *mthumb*/*mcpu=arm7* -# # Note: the multilib_exceptions matches both -mthumb and -# # -mthumb-interwork -# # -# # We have to match all the arm cpu variants which do not have the -# # multiply instruction and treat them as if the user had specified -# # -mcpu=arm7. Note that in the following the ? is interpreted as -# # an = for the purposes of matching command line options. -# # FIXME: There ought to be a better way to do this. -# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm7d -# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm7di -# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm70 -# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm700 -# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm700i -# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm710 -# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm710c -# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm7100 -# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm7500 -# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm7500fe -# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm6 -# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm60 -# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm600 -# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm610 -# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm620 +MULTILIB_MATCHES += march?armv6s-m=mcpu?cortex-m0 +MULTILIB_MATCHES += march?armv6s-m=mcpu?cortex-m1 +MULTILIB_MATCHES += march?armv7-m=mcpu?cortex-m3 +MULTILIB_MATCHES += march?armv7e-m=mcpu?cortex-m4 +MULTILIB_MATCHES += march?armv7e-m=mcpu?cortex-m4f + +MULTILIB_OPTIONS += mthumb +MULTILIB_DIRNAMES += thumb +MULTILIB_EXCEPTIONS += * + +MULTILIB_OPTIONS += march=armv6s-m/march=armv7-m/march=armv7e-m +MULTILIB_DIRNAMES += armv6s-m armv7-m armv7e-m +MULTILIB_EXCEPTIONS += * + +MULTILIB_OPTIONS += mfloat-abi=hard +MULTILIB_DIRNAMES += fpu +MULTILIB_EXCEPTIONS += * + +MULTILIB_OPTIONS += mfpu=fpv4-sp-d16 +MULTILIB_DIRNAMES += fpv4-sp-d16 +MULTILIB_EXCEPTIONS += * + +MULTILIB_REQUIRED += mthumb/march=armv6s-m +MULTILIB_REQUIRED += mthumb/march=armv7-m +MULTILIB_REQUIRED += mthumb/march=armv7e-m +MULTILIB_REQUIRED += mthumb/march=armv7e-m/mfloat-abi=hard/mfpu=fpv4-sp-d16
../gcc-4.9.1/configure --target=arm-none-eabi \ --prefix=/opt/cross-cortex-m3 \ --with-newlib \ --with-build-time-tools=/opt/cross-cortex-m3/arm-none-eabi/bin \ --with-sysroot=/opt/cross-cortex-m3/arm-none-eabi \ --disable-shared \ --enable-interwork \ --enable-nls \ --enable-poison-system-directories \ --enable-lto \ --enable-gold \ --disable-libmudflap \ --disable-libgomp \ --disable-libstdcxx-pch \ --disable-libssp \ --disable-tls \ --disable-threads \ --disable-libunwind-exceptions \ --enable-checking=release --without-headers --enable-languages=c
编译安装gcc
make all-gcc -j8 CFLAGS_FOR_TARGET="-ffunction-sections -fdata-sections -mabi=aapcs -Os -DPREFER_SIZE_OVER_SPEED -D__OPTIMIZE_SIZE__ -D__BUFSIZ__=64 -D_REENT_SMALL -fno-unroll-loops -DSMALL_MEMORY -ffast-math -ftree-vectorize" LDFLAGS_FOR_TARGET="-ffunction-sections -fdata-sections -mabi=aapcs -Os -DPREFER_SIZE_OVER_SPEED -D__OPTIMIZE_SIZE__ -D__BUFSIZ__=64 -D_REENT_SMALL -fno-unroll-loops -DSMALL_MEMORY -ffast-math -ftree-vectorize" make install-gcc
newlib配置(打补丁patch -N ${NEWLIB_VERSION}/libgloss/arm/linux-crt0.c newlib-optimize.patch):
--- linux-crt0.c +++ linux-crt0.c @@ -22,7 +22,10 @@ asm("\n" "\tbx r0\n" ".size _start, .-_start\n"); -__attribute__((naked, used)) +/* Force _start_thumb in the .text section so this will still compile when + * enabling -ffunction-sections. + */ +__attribute__((naked, used)) __attribute__((section(".text"))) static void _start_thumb(void) #else __attribute__((naked))
../newlib-nano-1.0/configure \ --target=arm-none-eabi \ --prefix=/opt/cross-cortex-m3 \ --enable-target-optspace \ --enable-newlib-reent-small \ --with-build-time-tools=/opt/cross-cortex-m3/bin \ --with-sysroot=/opt/cross-cortex-m3/arm-none-eabi \ --disable-shared \ --disable-newlib-supplied-syscalls \ --enable-multilib \ --enable-interwork \ --enable-newlib-nano-malloc \ --enable-newlib-io-c99-formats \ --enable-newlib-io-long-long \ --enable-lto
编译安装newlib-nano
make -j8 CFLAGS_FOR_TARGET="-ffunction-sections -fdata-sections -mabi=aapcs -Os -DPREFER_SIZE_OVER_SPEED -D__OPTIMIZE_SIZE__ -D__BUFSIZ__=64 -D_REENT_SMALL -fno-unroll-loops -DSMALL_MEMORY -ffast-math -ftree-vectorize" LDFLAGS_FOR_TARGET="-ffunction-sections -fdata-sections -mabi=aapcs -Os -DPREFER_SIZE_OVER_SPEED -D__OPTIMIZE_SIZE__ -D__BUFSIZ__=64 -D_REENT_SMALL -fno-unroll-loops -DSMALL_MEMORY -ffast-math -ftree-vectorize" make install
libgcc编译(回到刚刚编译gcc的目录)
make all-target-libgcc -j8 CFLAGS_FOR_TARGET="-ffunction-sections -fdata-sections -mabi=aapcs -Os -DPREFER_SIZE_OVER_SPEED -D__OPTIMIZE_SIZE__ -D__BUFSIZ__=64 -D_REENT_SMALL -fno-unroll-loops -DSMALL_MEMORY -ffast-math -ftree-vectorize" LDFLAGS_FOR_TARGET="-ffunction-sections -fdata-sections -mabi=aapcs -Os -DPREFER_SIZE_OVER_SPEED -D__OPTIMIZE_SIZE__ -D__BUFSIZ__=64 -D_REENT_SMALL -fno-unroll-loops -DSMALL_MEMORY -ffast-math -ftree-vectorize" make install-target-libgcc
gdb配置编译:
../gdb-7.7/configure --enable-multilib \ --enable-interwork --enable-sim \ --enable-sim-stdio --target=arm-none-eabi \ --prefix=/opt/cross-cortex-m3 make -j8 make install
qemu配置编译(libsdl-dev):
./configure --prefix=/opt/qemu \ --target-list=arm-softmmu \ --enable-sdl --enable-debug make -j8 make install
3.结尾
到这里工具包已经编译好了,可以使用本文章自带的hello代码测试下(记得在编译gcc之前添加PATH)(make QEMU)验证(第一个cortex-m3 hello,world程序留到下一篇解说)
lm3s6965.h
#ifndef LM3S6965_H #define UART_DR(baseaddr) (*(unsigned int *)(baseaddr)) #define UART_FR(baseaddr) (*(((unsigned int *)(baseaddr))+6)) enum { UART_FR_RXFE = 0x10, UART_FR_TXFF = 0x20, UART0_ADDR = 0x4000C000, }; #endif
lm3s6965.ld
MEMORY { FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 256K SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 32K } SECTIONS { .text : { _text = .; KEEP(*(.isr_vector)) *(.text*) *(.rodata*) _etext = .; } > FLASH .data : AT(ADDR(.text) + SIZEOF(.text)) { _data = .; *(vtable) *(.data*) _edata = .; } > SRAM .bss : { _bss = .; *(.bss*) *(COMMON) _ebss = .; } > SRAM . = ALIGN(32); /*Not sure if this needs to be done, but why not.*/ _stack_bottom = .; /*Address of the bottom of the stack.*/ . = . + 0x1000; /*Allocate 4K for the Stack.*/ _stack_top = .; /*Address of the top of the stack.*/ _heap_bottom = .; /*Address of the bottom of the heap.*/ _heap_top = 0x20008000; /*Address of the top of the heap, also end of RAM.*/ }
syscalls.c
#ifdef __cplusplus extern "C" { #endif #include "lm3s6965.h" #include <sys/types.h> static char *heap_end = 0; extern unsigned long _heap_bottom; extern unsigned long _heap_top; extern unsigned long g_ulBase; int _close(int file){ return -1; } int _fstat(int file){ return 0; } int _isatty(int file){ return 1; } int _lseek(int file, int ptr, int dir){ return 0; } int _open(const char *name, int flags, int mode){ return -1; } int _read(int file, char *ptr, int len){ // int todo; // char ch; // for (todo = 0; todo < len; todo++, ptr++){ // while(UART_FR(UART0_ADDR) & UART_FR_RXFE) // ; // *ptr = UART_DR(UART0_ADDR); //获取字符 // UART_DR(UART0_ADDR) = *ptr; //回显 // if(UART_FR(UART0_ADDR) & UART_FR_RXFE){ // break; // } // } return len; } int _write(int file, char *ptr, int len){ int todo; for (todo = 0; todo < len; todo++){ UART_DR(UART0_ADDR) = *ptr++; } return len; } caddr_t _sbrk(unsigned int incr){ char *prev_heap_end; if (heap_end == 0){ heap_end = (caddr_t)&_heap_bottom; } prev_heap_end = heap_end; if (heap_end + incr > (caddr_t)&_heap_top){ return (caddr_t)0; } heap_end += incr; return (caddr_t) prev_heap_end; } #ifdef __cplusplus } #endif
startup.c
// Forward declaration of the default fault handlers. void ResetISR(void); static void NmiSR(void); static void FaultISR(void); static void IntDefaultHandler(void); // The entry point for the application. extern int main(void); // Symbols Created by the Linker extern unsigned long _etext; extern unsigned long _data; extern unsigned long _edata; extern unsigned long _bss; extern unsigned long _ebss; extern unsigned long _stack_bottom; extern unsigned long _stack_top; extern unsigned long _heap_bottom; extern unsigned long _heap_top; // The vector table. Note that the proper constructs must be placed on this to // ensure that it ends up at physical address 0x0000.0000. __attribute__ ((section(".isr_vector")))void (* const g_pfnVectors[])(void) = { 0, // StackPtr, set in RestetISR ResetISR, // The reset handler NmiSR, // The NMI handler FaultISR, // The hard fault handler IntDefaultHandler, // The MPU fault handler IntDefaultHandler, // The bus fault handler IntDefaultHandler, // The usage fault handler 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved IntDefaultHandler, // SVCall handler IntDefaultHandler, // Debug monitor handler 0, // Reserved IntDefaultHandler, // The PendSV handler IntDefaultHandler, // The SysTick handler IntDefaultHandler, // GPIO Port A IntDefaultHandler, // GPIO Port B IntDefaultHandler, // GPIO Port C IntDefaultHandler, // GPIO Port D IntDefaultHandler, // GPIO Port E IntDefaultHandler, // UART0 Rx and Tx IntDefaultHandler, // UART1 Rx and Tx IntDefaultHandler, // SSI0 Rx and Tx IntDefaultHandler, // I2C0 Master and Slave IntDefaultHandler, // PWM Fault IntDefaultHandler, // PWM Generator 0 IntDefaultHandler, // PWM Generator 1 IntDefaultHandler, // PWM Generator 2 IntDefaultHandler, // Quadrature Encoder 0 IntDefaultHandler, // ADC Sequence 0 IntDefaultHandler, // ADC Sequence 1 IntDefaultHandler, // ADC Sequence 2 IntDefaultHandler, // ADC Sequence 3 IntDefaultHandler, // Watchdog timer IntDefaultHandler, // Timer 0 subtimer A IntDefaultHandler, // Timer 0 subtimer B IntDefaultHandler, // Timer 1 subtimer A IntDefaultHandler, // Timer 1 subtimer B IntDefaultHandler, // Timer 2 subtimer A IntDefaultHandler, // Timer 2 subtimer B IntDefaultHandler, // Analog Comparator 0 IntDefaultHandler, // Analog Comparator 1 IntDefaultHandler, // Analog Comparator 2 IntDefaultHandler, // System Control (PLL, OSC, BO) IntDefaultHandler, // FLASH Control IntDefaultHandler, // GPIO Port F IntDefaultHandler, // GPIO Port G IntDefaultHandler, // GPIO Port H IntDefaultHandler, // UART2 Rx and Tx IntDefaultHandler, // SSI1 Rx and Tx IntDefaultHandler, // Timer 3 subtimer A IntDefaultHandler, // Timer 3 subtimer B IntDefaultHandler, // I2C1 Master and Slave IntDefaultHandler, // Quadrature Encoder 1 IntDefaultHandler, // CAN0 IntDefaultHandler, // CAN1 IntDefaultHandler, // CAN2 IntDefaultHandler, // Ethernet IntDefaultHandler, // Hibernate IntDefaultHandler, // USB0 IntDefaultHandler, // PWM Generator 3 IntDefaultHandler, // uDMA Software Transfer IntDefaultHandler, // uDMA Error IntDefaultHandler, // ADC1 Sequence 0 IntDefaultHandler, // ADC1 Sequence 1 IntDefaultHandler, // ADC1 Sequence 2 IntDefaultHandler, // ADC1 Sequence 3 IntDefaultHandler, // I2S0 IntDefaultHandler, // External Bus Interface 0 IntDefaultHandler, // GPIO Port J IntDefaultHandler, // GPIO Port K IntDefaultHandler, // GPIO Port L IntDefaultHandler, // SSI2 Rx and Tx IntDefaultHandler, // SSI3 Rx and Tx IntDefaultHandler, // UART3 Rx and Tx IntDefaultHandler, // UART4 Rx and Tx IntDefaultHandler, // UART5 Rx and Tx IntDefaultHandler, // UART6 Rx and Tx IntDefaultHandler, // UART7 Rx and Tx 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved IntDefaultHandler, // I2C2 Master and Slave IntDefaultHandler, // I2C3 Master and Slave IntDefaultHandler, // Timer 4 subtimer A IntDefaultHandler, // Timer 4 subtimer B 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved IntDefaultHandler, // Timer 5 subtimer A IntDefaultHandler, // Timer 5 subtimer B IntDefaultHandler, // Wide Timer 0 subtimer A IntDefaultHandler, // Wide Timer 0 subtimer B IntDefaultHandler, // Wide Timer 1 subtimer A IntDefaultHandler, // Wide Timer 1 subtimer B IntDefaultHandler, // Wide Timer 2 subtimer A IntDefaultHandler, // Wide Timer 2 subtimer B IntDefaultHandler, // Wide Timer 3 subtimer A IntDefaultHandler, // Wide Timer 3 subtimer B IntDefaultHandler, // Wide Timer 4 subtimer A IntDefaultHandler, // Wide Timer 4 subtimer B IntDefaultHandler, // Wide Timer 5 subtimer A IntDefaultHandler, // Wide Timer 5 subtimer B IntDefaultHandler, // FPU IntDefaultHandler, // PECI 0 IntDefaultHandler, // LPC 0 IntDefaultHandler, // I2C4 Master and Slave IntDefaultHandler, // I2C5 Master and Slave IntDefaultHandler, // GPIO Port M IntDefaultHandler, // GPIO Port N IntDefaultHandler, // Quadrature Encoder 2 IntDefaultHandler, // Fan 0 0, // Reserved IntDefaultHandler, // GPIO Port P (Summary or P0) IntDefaultHandler, // GPIO Port P1 IntDefaultHandler, // GPIO Port P2 IntDefaultHandler, // GPIO Port P3 IntDefaultHandler, // GPIO Port P4 IntDefaultHandler, // GPIO Port P5 IntDefaultHandler, // GPIO Port P6 IntDefaultHandler, // GPIO Port P7 IntDefaultHandler, // GPIO Port Q (Summary or Q0) IntDefaultHandler, // GPIO Port Q1 IntDefaultHandler, // GPIO Port Q2 IntDefaultHandler, // GPIO Port Q3 IntDefaultHandler, // GPIO Port Q4 IntDefaultHandler, // GPIO Port Q5 IntDefaultHandler, // GPIO Port Q6 IntDefaultHandler, // GPIO Port Q7 IntDefaultHandler, // GPIO Port R IntDefaultHandler, // GPIO Port S IntDefaultHandler, // PWM 1 Generator 0 IntDefaultHandler, // PWM 1 Generator 1 IntDefaultHandler, // PWM 1 Generator 2 IntDefaultHandler, // PWM 1 Generator 3 IntDefaultHandler // PWM 1 Fault }; void ResetISR(void){ unsigned long *pulSrc, *pulDest; // Copy the data segment initializers from flash to SRAM. pulSrc = &_etext; for(pulDest = &_data; pulDest < &_edata; ){ *pulDest++ = *pulSrc++; } //Load the Stack Pointer __asm(" ldr sp, = _stack_top\n"); // Zero fill the bss segment. __asm(" ldr r0, =_bss\n" " ldr r1, =_ebss\n" " mov r2, #0\n" " .thumb_func\n" "zero_loop:\n" " cmp r0, r1\n" " it lt\n" " strlt r2, [r0], #4\n" " blt zero_loop"); // Call the application's entry point. main(); while(1){;} } static void NmiSR(void){ while(1); } static void FaultISR(void){ while(1); } static void IntDefaultHandler(void){ while(1); }
main.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "lm3s6965.h" void ResetISR(void); int main(){ printf("\nResetISR:%x\n", ResetISR); printf("testing lm3s6965...\nAddress\n"); char * p = NULL; p = (char *) malloc(sizeof(char)*100); if(p == NULL){ printf("malloc error!!!\n"); while(1){;} } strcpy(p, "!!!Hello, World!!!"); for(;*p != 0;p++){ printf("0x%x %c\n",p,*p); } printf("\nDead cycle...\n"); while(1){;} return 0; }
Makefile
CC = arm-none-eabi-gcc OBJCOPY = arm-none-eabi-objcopy OBJDUMP = arm-none-eabi-objdump ARM = qemu-system-arm main.bin:main.c syscalls.c startup.c $(CC) -std=c11 -g -mcpu=cortex-m3 -mthumb -nostartfiles -T lm3s6965.ld syscalls.c startup.c main.c -o main $(OBJCOPY) -O binary -S -R .note -R .comment main main.bin $(OBJDUMP) -S main > main.list QEMU: main.bin $(ARM) -M lm3s6965evb --kernel main.bin --serial stdio #-nographic DEBUG: main.bin $(ARM) -M lm3s6965evb -nographic -monitor null -serial null -semihosting -kernel main.bin -S -gdb tcp::123456 clean: main.bin rm main.bin main main.list
作者:不一样的四季
email:[email protected]
发表于:2014.10.15