LPC1114+CMSIS Libraryでprintfを使ってみた
LPC11xx_cmsis2_Libに実装されているUARTSend関数を使ってシリアル出力していたが
文字列以外の表示が面倒なのでprintfを使えるようにした。
今の所2種類の方法で動いたので両方メモしておく。
試した環境
- LPCXpresso_7.7.2_379
- LPCXpresso1114_cmsis2.zipをインポート済み
C:\nxp\LPCXpresso_7.7.2_379\lpcxpresso\Examples\NXP\LPC1000\LPC11xxにある - Redlib(none)
- LPC-Link2(Semihostingを使う際は必要)
Semihostingを使う
LPC-Link2があるならSemihostingを使うとLPCXpresso上でprintfの結果が見える。
使い方も簡単でNew project
でC Project (Semihosted)
を選ぶだけ。
出てきたサンプルコードを実行するとLPCXpresso上のConsoleにHello Worldが表示される。
syscallを実装してUART経由でprintfを使う
New project
->C Project
で作成したプロジェクト上でprintfを呼び出すと
Redlib(none)ではSystemcallが実装されていないのでリンク時エラーが発生する。
c:/nxp/lpcxpresso_7.7.2_379/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv6-m\libcr_c.a(fpprintf.o): In function `printf': fpprintf.c:(.text.printf+0x38): undefined reference to `__sys_write' c:/nxp/lpcxpresso_7.7.2_379/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv6-m\libcr_c.a(_deferredlazyseek.o): In function `__flsbuf': _deferredlazyseek.c:(.text.__flsbuf+0x88): undefined reference to `__sys_istty' c:/nxp/lpcxpresso_7.7.2_379/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv6-m\libcr_c.a(_writebuf.o): In function `_Cwritebuf': _writebuf.c:(.text._Cwritebuf+0x16): undefined reference to `__sys_flen' _writebuf.c:(.text._Cwritebuf+0x26): undefined reference to `__sys_seek' _writebuf.c:(.text._Cwritebuf+0x3a): undefined reference to `__sys_write' c:/nxp/lpcxpresso_7.7.2_379/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv6-m\libcr_c.a(alloc.o): In function `_Csys_alloc': alloc.c:(.text._Csys_alloc+0xe): undefined reference to `__sys_write' alloc.c:(.text._Csys_alloc+0x12): undefined reference to `__sys_appexit' c:/nxp/lpcxpresso_7.7.2_379/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv6-m\libcr_c.a(fseek.o): In function `fseek': fseek.c:(.text.fseek+0x18): undefined reference to `__sys_istty' fseek.c:(.text.fseek+0x3c): undefined reference to `__sys_flen' collect2.exe: error: ld returned 1 exit status
Systemcallの定義はlibconfig-arm.hに記述されているので適当に実装してみた。
以下サンプルコード
#ifdef __USE_CMSIS #include "LPC11xx.h" #endif #include <stdlib.h> #include <stdio.h> #include <string.h> #include "uart.h" #include <cr_section_macros.h> // TODO: insert other include files here // TODO: insert other definitions and declarations here void uart_putc(const char); ////////////////////////// Systemcall ////////////////////////// int __sys_write(int iFileHandle, char *pcBuffer, int iLength) { int n; for (n = 0; n < iLength; n++) { if (pcBuffer[n] == '\n'){ uart_putc('\r'); } uart_putc(pcBuffer[n]); } return iLength; } int __sys_istty(int handle) { return 1; } int __sys_flen(int handle) { return 0; } int __sys_seek(int handle, int pos) { return 0; } void __sys_appexit (void) { } ////////////////////////// UART //////////////////////// // send a character via TXD void uart_putc(const char c) { // Wait for TX buffer empty while (!(LPC_UART->LSR & LSR_THRE)); // Put a character LPC_UART->THR = c; } ////////////////////////// Main ////////////////////////// int main(void) { UARTInit(115200); // Force the counter to be placed into memory volatile static int i = 0 ; // Enter an infinite loop, just incrementing a counter while(1) { i++ ; if (i % 1000000 == 0){ printf("i = %d(dec) ",i); printf("%08x(hex)\n",i); } } return 0 ; }
uart_putc関数はエレキジャックのHPにあったコード*1を
そのまま使わせて頂きました。
実行するとUARTからprintfの結果が送られてくる。
i = 1000000(dec) 000f4240(hex) i = 2000000(dec) 001e8480(hex) i = 3000000(dec) 002dc6c0(hex) i = 4000000(dec) 003d0900(hex)
scanf
printfが動作したので、ついでにscanfも実装しようとしたがうまく動かなかった。
__sys_read
と__sys_read_c
を追加で実装したが
デバック実行でブレイクポイントを設定しても止まらなかった。
Redlib内の動きが分かれば良いのだが
ソースコードは公開されていない為scanfの実装はあきらめる。