0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

STM32でlibopencm3を使ってUART

Last updated at Posted at 2016-10-28

libopencm3を使ってUART出力をしてみました。

libopencm3は、Cortex Mシリーズ向けの LGPLv3なライブラリです。

Macで作業しました。(あまりMacに依存する内容ではないです。)

使用ハードウェア

  • ST NUCLEO-F103RB
  • 秋月電子で購入
  • STM32F103RBT6が載っている。
  • ボードのバージョンはMB1136 C-03
  • ST-LINKが内蔵されている。 ST-LINKのFWを最新版に上げてから使いました。
  • LEDはPA5に接続されている。
  • UARTはUSART2がST-LINKに繋がっています。ST-LINKのUSBシリアル経由でアクセスができます。USART2のTXはPA2です。

コンパイラなどのインストール

サンプルコード

  • UARTのサンプルは https://github.com/libopencm3/libopencm3-examples/blob/master/examples/stm32/f1/stm32-h103/usart/usart.c を参考にしました。
  • コードの説明
  • rcc_clock_setup_in_hse_8mhz_out_72mhz() HSEを使って内部クロックを72MHzに設定。
  • rcc_periph_clock_enable() PORTAとUSART2にクロックを供給。
  • gpio_set_mode() PA2を、GPIO_CNF_OUTPUT_ALTFN_PUSHPULLに設定。 こうするとUSART2_TXの機能にに割り当てられる。 STM32では、ALTFN/AF/オルタナティブファンクション に設定すると、PINがUARTなどの機能に割り当てられる。 ピンが多いパッケージの場合はさらにピンのリマップができる。
  • usart_set_ で始まる関数でUARTの設定を行う。
  • usart_enable()で USART2を有効化
  • usart_send_blocking()で1バイト送信する。
uart.c
# include <libopencm3/stm32/rcc.h>
# include <libopencm3/stm32/gpio.h>
# include <libopencm3/stm32/usart.h>

static void clock_setup(void)
{
  rcc_clock_setup_in_hse_8mhz_out_72mhz();

  /* Enable GPIOA clock. */
  rcc_periph_clock_enable(RCC_GPIOA);

  /* Enable clocks for USART2. */
  rcc_periph_clock_enable(RCC_USART2);
}

static void usart_setup(void)
{
  /* Setup GPIO pin GPIO_USART2_TX. */
  gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
          GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);

  /* Setup UART parameters. */
  usart_set_baudrate(USART2, 38400);
  usart_set_databits(USART2, 8);
  usart_set_stopbits(USART2, USART_STOPBITS_1);
  usart_set_mode(USART2, USART_MODE_TX);
  usart_set_parity(USART2, USART_PARITY_NONE);
  usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);

  /* Finally enable the USART. */
  usart_enable(USART2);
}

static void gpio_setup(void)
{
  gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
                GPIO_CNF_OUTPUT_PUSHPULL, GPIO5);
}

int main(void)
{
  int i, j = 0, c = 0;

  clock_setup();
  gpio_setup();
  usart_setup();

  /* Blink the LED (PA5) on the board with every transmitted byte. */
  while (1) {
    gpio_toggle(GPIOA, GPIO5);  /* LED on/off */
    usart_send_blocking(USART2, c + '0');  /* USART2: Send byte. */
    c = (c == 9) ? 0 : c + 1;  /* Increment c. */
    if ((j++ % 80) == 0) {  /* Newline after line full. */
      usart_send_blocking(USART2, '\r');
      usart_send_blocking(USART2, '\n');
    }
    for (i = 0; i < 800000; i++)  /* Wait a bit. */
      __asm__("nop");
  }

  return 0;
}

コンパイル

  • makefile
# Makefile

###############################################################################

PROGRAM  = stm32-uart
CROSS   ?= arm-none-eabi
OBJS     = uart.o 

###############################################################################

ARCH_FLAGS = -DSTM32F1 -mthumb -mcpu=cortex-m3 -msoft-float -mfix-cortex-m3-ldrd
LDSCRIPT   = libopencm3/lib/stm32/f1/stm32f103xb.ld
LIBOPENCM3 = libopencm3/lib/libopencm3_stm32f1.a
OPENCM3_MK = lib/stm32/f1

###############################################################################

CC       = $(CROSS)-gcc
LD       = $(CROSS)-ld
OBJCOPY  = $(CROSS)-objcopy
OBJDUMP  = $(CROSS)-objdump
SIZE     = $(CROSS)-size

ELF      = $(PROGRAM).elf
BIN      = $(PROGRAM).bin
MAP      = $(PROGRAM).map
DMP      = $(PROGRAM).out

all:
        @make firmware

CFLAGS  += -O3 -Wall -g
CFLAGS  += -fno-common -ffunction-sections -fdata-sections
CFLAGS  += $(ARCH_FLAGS) -Ilibopencm3/include/ $(EXTRA_CFLAGS)

LIBC     = $(shell $(CC) $(CFLAGS) --print-file-name=libc.a)
LIBNOSYS = $(shell $(CC) $(CFLAGS) --print-file-name=libnosys.a)
LIBGCC   = $(shell $(CC) $(CFLAGS) --print-libgcc-file-name)

# LDPATH is required for libopencm3 ld scripts to work.
LDPATH   = libopencm3/lib/
LDFLAGS += -L$(LDPATH) -T$(LDSCRIPT) -Map $(MAP) --gc-sections
LDLIBS  += $(LIBOPENCM3) $(LIBC) $(LIBNOSYS) $(LIBGCC)

firmware: $(LIBOPENCM3) $(BIN) $(DMP) size

$(ELF): $(LDSCRIPT) $(OBJS)
        $(LD) -o $@ $(LDFLAGS) $(OBJS) $(LDLIBS)

$(DMP): $(ELF)
        $(OBJDUMP) -d $< > $@

%.bin: %.elf
        $(OBJCOPY) -S -O binary $< $@

%.o: %.c board.h
        $(CC) $(CFLAGS) -c $< -o $@

$(LIBOPENCM3):
        CFLAGS="$(CFLAGS)" make -C libopencm3 $(OPENCM3_MK) V=1


.PHONY: clean size

clean:
        rm -f $(OBJS) $(ELF) $(BIN) $(MAP) $(DMP) 


size: $(PROGRAM).elf
        @echo ""
        @$(SIZE) $(PROGRAM).elf
        @echo ""
  • libopencm3をgitで持ってくる。
$ git clone https://github.com/libopencm3/libopencm3.git
  • makeする。 (makeするとlibopencm3もコンパイルするが、ログは割愛)
$ make
arm-none-eabi-gcc -O3 -Wall -g -fno-common -ffunction-sections -fdata-sections -DSTM32F1 -mthumb -mcpu=cortex-m3 -msoft-float -mfix-cortex-m3-ldrd -Ilibopencm3/include/  -c uart.c -o uart.o
arm-none-eabi-ld -o stm32-uart.elf -Llibopencm3/lib/ -Tlibopencm3/lib/stm32/f1/stm32f103xb.ld -Map stm32-uart.map --gc-sections uart.o  libopencm3/lib/libopencm3_stm32f1.a /usr/local/Cellar/gcc-arm-none-eabi-49/20150609/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m/libc.a /usr/local/Cellar/gcc-arm-none-eabi-49/20150609/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m/libnosys.a /usr/local/Cellar/gcc-arm-none-eabi-49/20150609/bin/../lib/gcc/arm-none-eabi/4.9.3/armv7-m/libgcc.a
arm-none-eabi-objcopy -S -O binary stm32-uart.elf stm32-uart.bin
arm-none-eabi-objdump -d stm32-uart.elf > stm32-uart.out

   text	   data	    bss	    dec	    hex	filename
   1300	     12	      0	   1312	    520	stm32-uart.elf

ダウンロード

  • st-flashを使ってstm32-uart.binをflashのある0x8000000に書き込む。
$ st-flash write stm32-uart.bin  0x8000000
2016-10-29T07:43:25 INFO /tmp/stlink-20160608-18806-p6zk82/stlink-1.2.0/src/stlink-common.c: Loading device parameters....
2016-10-29T07:43:25 INFO /tmp/stlink-20160608-18806-p6zk82/stlink-1.2.0/src/stlink-common.c: Device connected is: F1 Medium-density device, id 0x20036410
2016-10-29T07:43:25 INFO /tmp/stlink-20160608-18806-p6zk82/stlink-1.2.0/src/stlink-common.c: SRAM size: 0x5000 bytes (20 KiB), Flash: 0x20000 bytes (128 KiB) in pages of 1024 bytes
2016-10-29T07:43:25 INFO /tmp/stlink-20160608-18806-p6zk82/stlink-1.2.0/src/stlink-common.c: Attempting to write 1312 (0x520) bytes to stm32 address: 134217728 (0x8000000)
Flash page at addr: 0x08000400 erased
2016-10-29T07:43:25 INFO /tmp/stlink-20160608-18806-p6zk82/stlink-1.2.0/src/stlink-common.c: Finished erasing 2 pages of 1024 (0x400) bytes
2016-10-29T07:43:25 INFO /tmp/stlink-20160608-18806-p6zk82/stlink-1.2.0/src/stlink-common.c: Starting Flash write for VL/F0/F3 core id
2016-10-29T07:43:25 INFO /tmp/stlink-20160608-18806-p6zk82/stlink-1.2.0/src/stlink-common.c: Successfully loaded flash loader in sram
  1/1 pages written
2016-10-29T07:43:25 INFO /tmp/stlink-20160608-18806-p6zk82/stlink-1.2.0/src/stlink-common.c: Starting verification of write complete
2016-10-29T07:43:25 INFO /tmp/stlink-20160608-18806-p6zk82/stlink-1.2.0/src/stlink-common.c: Flash written and verified! jolly good!

動作確認

  • ST-LINKのUSBシリアルのデバイス名は、 ls してみて、USBを挿したら表示されるデバイスを探してください。
$ls -l /dev/tty.*
/dev/tty.usbmodem1423
  • UART出力を確認するのにcuを使いました。速度を38400bpsに設定します。
$ sudo cu -l  /dev/tty.usbmodem1423 -s 38400
Connected.
6789012345678901234567890123456789012345678901234567890
12345678901234567890123456789012345678901234567890123456789012345678901234567890
12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • cuを停止するときは ~. を入力します。

その他

  • はじめ、基板のPA2のコネクタを見ていたら、UART出力されないなぁと思って、チップのPA2の端子を見たら、出力されているのを見つけて、NUCLEOのドキュメントを読んだらUSBシリアルにつながっていると書いてあるのを発見しました。ちゃんとドキュメントを読みましょう。
  • libopencm3はサンプルコードがたくさんあるのと、githubから持ってきてgccでコンパイルが通るのが良いです。
  • PA2の端子に直結した場合、UART出力は2Mbpsで動作することを確認しました。
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?