CubeMX 4.23.0 + STM32CubeL1 1.8.0でCOMP2からのトリガをキャプチャする [電子工作]
L0とかF0のシリーズでは対応してるのになんでやー!?
ということで、設定ファイルを解析してL1でもCubeMXのPinout設定において、
TIM2,3,4のChannel4で"Input Capture direct from COMPx"を設定できるようにしてみた。
※L1のラインは売れ線じゃないんですかねー?その割にL0って流通してるように見えないんですけど。
L151/152CxTx以外は検証してません
条件をちゃんと設定していないので、COMPxからのdirectに対応していないタイマーでも設定できちゃうかも。
ということで、設定ファイルを解析してL1でもCubeMXのPinout設定において、
TIM2,3,4のChannel4で"Input Capture direct from COMPx"を設定できるようにしてみた。
※L1のラインは売れ線じゃないんですかねー?その割にL0って流通してるように見えないんですけど。
L151/152CxTx以外は検証してません
条件をちゃんと設定していないので、COMPxからのdirectに対応していないタイマーでも設定できちゃうかも。
~/STM32CubeMX/db/mcu/IP$ diff -uN TIM1_8L1-gptimer2_v2_x_Cube_Modes.xml_orig TIM1_8L1-gptimer2_v2_x_Cube_Modes.xml --- TIM1_8L1-gptimer2_v2_x_Cube_Modes.xml_orig2017-11-06 21:39:17.314001382 +0900 +++ TIM1_8L1-gptimer2_v2_x_Cube_Modes.xml2017-11-06 21:50:33.434001382 +0900 @@ -1303,6 +1303,7 @@+ TIM_MasterConfigSynchronization TIM_ConfigBreakDeadTime @@ -3263,6 +3264,14 @@+ + Semaphore_input_Channel4$IpInstance +Semaphore_input_Channel4_direct$IpInstance +Semaphore_CH4pinUsed$IpInstance ++ ++ Semaphore_input_Channel4$IpInstance Semaphore_input_Channel4_indirect$IpInstance
STM32L151とCubeMXでfreeRTOS [電子工作]
例によってLaunchpadのGNU ARM Embedded Toolchain環境とOpenOCD+CMSIS-DAP
罠っていうかSTM32L1用のFWバグってるじゃんという
1. CubeMXでプロジェクト作成
[Pinout]
・[Middlewares]-[FREERTOS]-[Enabled]をチェック
※以下はそれぞれのボードに合わせて
・[Peripherals]-[RCC]-[High Speed Clock (HSE)]を'Crystal/Ceramic Resonator'
・[SYS]-[Debug]を'Serial Wire'
※テスト用のLED出力ピン
・PC13
GPIO_Output, ラベル='LED1'
・PC14
GPIO_Output, ラベル='LED2'
[Clock Configuration]
System Clock MuxでHSEを選択
[Configuration]
FREERTOSの設定
[Config parametes]
・[Memory management settings]-[Memory Management scheme]がデフォルトで'heap_4'なので'heap_1'に変更
(しなくてもいいけど)
[Task and Queues]
・LED1TaskとLED2Taskを、それぞれosPriorityNormalで設定
-> [Project]-[Settings]-[Project]で[Toolchain / IDE]を'SW4STM32'にして、Code Generate
2. makefile
こんな感じ
3. ソース修正!
クロックソースをMSI以外にしている場合、'STM32Cube FW_L1 V1.6.0'のSystemClock_Config()ではバグっていて起動しません。
(コンパイルオプションと運次第では起動することもある)
void SystemClock_Config(void)の下記の部分で、RCC_OSCILLATORTYPE_MSIを削除
やらなくてもいいけれど、使わないMSIを止めたい場合は
HAL_RCC_ClockConfigでSYSCLKSourceを変更した後で
4. テスト用のTaskの実装
適当に
罠っていうかSTM32L1用のFWバグってるじゃんという
1. CubeMXでプロジェクト作成
[Pinout]
・[Middlewares]-[FREERTOS]-[Enabled]をチェック
※以下はそれぞれのボードに合わせて
・[Peripherals]-[RCC]-[High Speed Clock (HSE)]を'Crystal/Ceramic Resonator'
・[SYS]-[Debug]を'Serial Wire'
※テスト用のLED出力ピン
・PC13
GPIO_Output, ラベル='LED1'
・PC14
GPIO_Output, ラベル='LED2'
[Clock Configuration]
System Clock MuxでHSEを選択
[Configuration]
FREERTOSの設定
[Config parametes]
・[Memory management settings]-[Memory Management scheme]がデフォルトで'heap_4'なので'heap_1'に変更
(しなくてもいいけど)
[Task and Queues]
・LED1TaskとLED2Taskを、それぞれosPriorityNormalで設定
-> [Project]-[Settings]-[Project]で[Toolchain / IDE]を'SW4STM32'にして、Code Generate
2. makefile
こんな感じ
PROJECT = stm32l151 DIR=~/gcc-arm/bin CC=$(DIR)/arm-none-eabi-gcc NM=$(DIR)/arm-none-eabi-nm CP=$(DIR)/arm-none-eabi-objcopy OD=$(DIR)/arm-none-eabi-objdump SZ=$(DIR)/arm-none-eabi-size # SEMIHOST_LIB = --specs=rdimon.specs -lrdimon NANOLIB = --specs=nosys.specs --specs=nano.specs OPENOCD=~/openocd TARGETCNF=stm32l1.cfg #INTERFACECNF=stlink-v2-1.cfg INTERFACECNF=cmsis-dap.cfg DEFS = -DUSE_HAL_DRIVER -DSTM32L151xB -DGCC_ARMCM3 MCU = cortex-m3 MCFLAGS = -MD -mcpu=$(MCU) -march=armv7-m -mtune=$(MCU) MCFLAGS += -std=gnu99 MCFLAGS += -mthumb -mlittle-endian -mno-unaligned-access -mno-sched-prolog # MCFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 MCFLAGS += -fno-strict-aliasing -fsigned-char MCFLAGS += -ffunction-sections -fdata-sections MCFLAGS += -fno-schedule-insns2 MCFLAGS += -fno-common -fno-hosted MCFLAGS += -mthumb-interwork MCFLAGS += -fmessage-length=0 MCFLAGS += -ffreestanding MCFLAGS += -fno-move-loop-invariants MCFLAGS += -fsingle-precision-constant # MCFLAGS += -nostartfiles MCFLAGS += -Wl,--gc-sections # MCFLAGS += -u _printf_float STM32_INCLUDES = \ -IInc \ -IDrivers/CMSIS/Device/ST/STM32L1xx/Include \ -IDrivers/CMSIS/Include \ -IDrivers/STM32L1xx_HAL_Driver/Inc/Legacy \ -IDrivers/STM32L1xx_HAL_Driver/Inc \ -IMiddlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS \ -IMiddlewares/Third_Party/FreeRTOS/Source/include \ -IMiddlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3 # OPTIMIZE = -gdwarf-2 -O0 -flto-partition=none -fipa-sra OPTIMIZE = -Os -finline -finline-functions-called-once CFLAGS = $(MCFLAGS) $(OPTIMIZE) $(NANOLIB) $(SEMIHOST_LIB) $(DEFS) $(STM32_INCLUDES) CFLAGS += -Wl,-cref -T STM32L151C8Tx_FLASH.ld AFLAGS = $(MCFLAGS) CSRC = \ $(wildcard Src/*.c) \ $(wildcard Drivers/STM32L1xx_HAL_Driver/Src/*.c) \ $(wildcard Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/*.c) \ $(wildcard Middlewares/Third_Party/FreeRTOS/Source/*.c) \ $(wildcard Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3/*.c) \ $(wildcard Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/*.c) \ $(wildcard Middlewares/Third_Party/FreeRTOS/Source/portable/*.c) ASRC = startup/startup_stm32l151xb.s COBJ = $(CSRC:.c=.o) AOBJ = $(ASRC:.s=.o) all: build size build: elf hex lst sym elf: $(PROJECT).elf hex: $(PROJECT).hex lst: $(PROJECT).lst sym: $(PROJECT).sym %.hex: %.elf @echo $(CP) -O ihex $< $@ %.lst: %.elf @echo $(OD) -h -S -C $< > $@ %.sym: %.elf @echo $(NM) -n $< > $@ size: @echo $(SZ) $(PROJECT).hex $(SZ) $(PROJECT).elf $(SZ) -A -x $(PROJECT).elf %.elf: $(AOBJ) $(COBJ) @echo $(CC) $(CFLAGS) $^ -o $@ $(COBJ) : %.o : %.c @echo $(CC) -c $(CFLAGS) $< -o $@ $(AOBJ) : %.o : %.s @echo $(CC) -c $(CFLAGS) $< -o $@ clean: @echo find . -name '*.o' -print -or -name '*.d' -print | xargs rm -f rm -f $(PROJECT).elf $(PROJECT).hex $(PROJECT).lst $(PROJECT).sym flash: $(PROJECT).elf # $(OPENOCD)/src/openocd -s $(OPENOCD)/tcl -f board/st_nucleo_l1.cfg -c "program $^ verify reset exit" $(OPENOCD)/src/openocd -s $(OPENOCD)/tcl -f interface/$(INTERFACECNF) -f target/$(TARGETCNF) -c "program $^ verify reset exit"
3. ソース修正!
クロックソースをMSI以外にしている場合、'STM32Cube FW_L1 V1.6.0'のSystemClock_Config()ではバグっていて起動しません。
(コンパイルオプションと運次第では起動することもある)
void SystemClock_Config(void)の下記の部分で、RCC_OSCILLATORTYPE_MSIを削除
/**Initializes the CPU, AHB and APB busses clocks */ // RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_MSI; RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); }
やらなくてもいいけれど、使わないMSIを止めたい場合は
HAL_RCC_ClockConfigでSYSCLKSourceを変更した後で
/**Initializes the CPU, AHB and APB busses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } /* ADD: stop MSI after changing SYSCLKSource */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI; RCC_OscInitStruct.MSIState = RCC_MSI_OFF; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); }
4. テスト用のTaskの実装
適当に
/* StartLED1Task function */ void StartLED1Task(void const * argument) { /* USER CODE BEGIN 5 */ /* Infinite loop */ for(;;) { HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, SET); osDelay(500); HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, RESET); osDelay(500); } /* USER CODE END 5 */ } /* StartLED2Task function */ void StartLED2Task(void const * argument) { /* USER CODE BEGIN StartLED2Task */ /* Infinite loop */ for(;;) { HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, SET); osDelay(1000); HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, RESET); osDelay(1000); } /* USER CODE END StartLED2Task */ }
秋月のMEMS発振器を買ってみた [電子工作]
(写真右 スマフォ撮影なのでぶれぶれなのはご容赦を)
特に使い道は考えてないですが、発振とマイコンへの入力だけ確認して見ました。
nucleo f303k8のOSC_IN(D7)に突っ込んでCubeMXで適当にLチカするだけ。
ただこいつ、普通に5mA近く食いやがります。
(データシートではno loadでTyp.3.8mA まあ適当なテスターなので気にしない方向で)
アイドル時には内部クロックに切り替えてoutput disableにする、って使い方かなあ。
写真左は、比較用に用意して見た同じく秋月で売ってるTCXO。
2.8V Typ.ですが電源電圧範囲:2.3 V ~ 3.6 Vって書いてあるので3.3V突っ込んで動かしてます。
出力が0.8Vppでそのままではマイコンに入れられないので、ワンゲートロジックを挟んでます。
(実装面積くいますね。ちょっとじゃま)
こっちだと消費電力は2.5mAくらい。うむむむ。
STM32 TIM17とDMA Channel1でDACを駆動する [電子工作]
STM32でDACをDMAで駆動する場合、通常はTIM6/7の出力をトリガイベントとしてDACに繋げるかと思います(リファレンスにもそう書いてあるし)。
が、
STM32F051ではDAC, USARTx_RX, SPI1_TX, I2Cx_RXでChannel3を取り合っているので
あまりChannel3を使いたくない気がします。
USARTのRXはDMA使わなくてもいーんじゃね?というとそのような気もしますが、
Channel1がなんとなくヒマそうなので、Channel1にリクエストできるTIM17を使ってやってみます。
CubeMXでの設定
TIM17
Prescaler (PSC - 16 bits value) : 0
Counter Mode : Up
Counter Period (AutoReload Register - 16 bits value ) : 3000-1 * (48MHz / 16KHz = 3000)
Internal Clock Division (CKD) : No Division
Repetition Counter (RCR - 8 bits value) : 0
auto-reload preload : Disable
DMA request : TIM17_CH1/UP
Stream : DMA1_Channel1
Direction : Memory To Peripheral
Priority : Low
TIM17_CH1/UP: DMA1_Channel1 DMA request Settings:
Mode: Circular *
Peripheral Increment: Disable
Memory Increment: Enable *
Peripheral Data Width: Half Word
Memory Data Width: Half Word
DAC Out1 Settings:
Output Buffer : Enable
Trigger : None
DACのTriggerをNoneにしておくのがミソです。
Code Generateして、main.cに以下を追記
Private Variables (16KHzサンプリングでの440Hzのサイン波)
デバイス初期化の後で
(DMAをCircularモードにしているので、止めない限り出力しっぱなし)
HAL_TIM_Base_Start_DMA()は、なぜかDMAの転送先をタイマのARRレジスタにしてしまうので、
参考にして開始処理を書いてみました。
が、
STM32F051ではDAC, USARTx_RX, SPI1_TX, I2Cx_RXでChannel3を取り合っているので
あまりChannel3を使いたくない気がします。
USARTのRXはDMA使わなくてもいーんじゃね?というとそのような気もしますが、
Channel1がなんとなくヒマそうなので、Channel1にリクエストできるTIM17を使ってやってみます。
CubeMXでの設定
TIM17
Prescaler (PSC - 16 bits value) : 0
Counter Mode : Up
Counter Period (AutoReload Register - 16 bits value ) : 3000-1 * (48MHz / 16KHz = 3000)
Internal Clock Division (CKD) : No Division
Repetition Counter (RCR - 8 bits value) : 0
auto-reload preload : Disable
DMA request : TIM17_CH1/UP
Stream : DMA1_Channel1
Direction : Memory To Peripheral
Priority : Low
TIM17_CH1/UP: DMA1_Channel1 DMA request Settings:
Mode: Circular *
Peripheral Increment: Disable
Memory Increment: Enable *
Peripheral Data Width: Half Word
Memory Data Width: Half Word
DAC Out1 Settings:
Output Buffer : Enable
Trigger : None
DACのTriggerをNoneにしておくのがミソです。
Code Generateして、main.cに以下を追記
Private Variables (16KHzサンプリングでの440Hzのサイン波)
const uint16_t sine_440[] = { 0x003, 0x022, 0x07E, 0x115, 0x1E1, 0x2DD, 0x401, 0x545, 0x69D, 0x800, 0x964, 0xABC, 0xC00, 0xD24, 0xE20, 0xEEC, 0xF83, 0xFDF, 0xFFF, 0xFDF, 0xF83, 0xEEC, 0xE20, 0xD24, 0xBFF, 0xABC, 0x964, 0x801, 0x69D, 0x545, 0x402, 0x2DD, 0x1E1, 0x115, 0x07E, 0x022 };
デバイス初期化の後で
(DMAをCircularモードにしているので、止めない限り出力しっぱなし)
/* Enable DAC */ HAL_DAC_Start(&hdac1, DAC_CHANNEL_1); /* Enable the DMA channel */ HAL_DMA_Start_IT(htim17.hdma[TIM_DMA_ID_UPDATE], (uint32_t)sine_440, (uint32_t)&(hdac1.Instance->DHR12R1), 36); /* Enable the TIM Update DMA request */ __HAL_TIM_ENABLE_DMA(&htim17, TIM_DMA_UPDATE); /* Enable the Peripheral (Start Timer) */ __HAL_TIM_ENABLE(&htim17);
HAL_TIM_Base_Start_DMA()は、なぜかDMAの転送先をタイマのARRレジスタにしてしまうので、
参考にして開始処理を書いてみました。
[電子工作] MacでSTM32の開発環境を GNU arm + OpenOCDで作ってみる - CubeMXのプロジェクトをどうにかする版 [電子工作]
いろいろリニューアル
前提環境
・MacBook Pro (15-inch, Early 2011)
・macOS Sierra バージョン 10.12.2
・make ... たぶんXCodeのコマンドラインツール
・MacPort 2.3.5 ... OpenOCDのビルド
・git ... MacPortでインストール
構築する環境
・launchpad GNU ARM Embedded Toolchain : 5-2016-q3-update
・OpenOCD : ソースからビルド, CMSIS-DAPとSTLinkに対応
・STM32CubeMX : 4.18.0
目標
・CubeMXで雛形を生成
・launchpadのGNU ARM Embedded Toolchainでビルドする
・テキストエディタ+makeで開発
・OpenOCDで書き込み & デバッグする
ターゲット
・Nucleo-F303RE ボード
おっきいボードに変えてみました
・CubeMXで雛形を生成してLチカ
手順1.arm-none-eabi-gccの入手
お手軽にlaunchpadからバイナリを入手します。
右のDownloadsのリストから、gcc-arm-none-eabi-5_4-2016q3-20160926-mac.tar.bz2をダウンロードし、
~/gcc_arm下に展開します。
(makefile使い回しの都合上、展開フォルダ名を変更しました)
手順2.OpenOCDのビルド
ソースからビルドします
makefile使い回しの都合上、HOMEディレクトリ直下に展開しています。
(Nucleoだけを使う場合はCMSIS-DAPは不要)
手順3.STM32 CubeMXの入手とインストール
STmicroのサイトからダウンロードします。
メールアドレスを入力するとダウンロードURLがメールで送られてきます。
ダウンロードしたファイル(en.stm32cubemx.zip)を展開し、SetupSTM32CubeMX-4.18.0.appを右クリック->開くで起動してインストール、、、
なのですが、理由はよくわかりませんが、Finderからインストーラが起動しません??
ターミナルを開いてzipを展開したフォルダに移動し、下記のようにインストーラを直で起動してインストールしました。
なんなんでしょうね?
インストールできたらApplicationフォルダからCubeMXを起動し、
[Help]-[Install New Libraries]で必要なMCU用のライブラリ(STM32CubeF3)をインストールします。
手順4.CubeMXでテンプレートを作成
[File]-[New Project...]を選択
[Board Selector]タブに切り替え
[Type of Board]で Nucleo64 を選択
[MCU Series]で STM32F3 を選択
[Boards List]から NUCLEO-F303RETx を選択
ペリフェラルの設定
・HSE外部クロック源 - STLinkからMCOに供給される外部クロック(8MHz)
RCC BYPASS Clock Source RCC_OSC_IN PF0-OSC_IN
・LSE外部クロック源 - Nucleoボードに載っているクリスタル(32.768KHz)
RCC Crystal/Ceramic Resonator RCC_OSC32_IN PC14-OSC32_IN
RCC Crystal/Ceramic Resonator RCC_OSC32_OUT PC15-OSC32_OUT
・SWD : SWOが使えるのかよくわからないけれど、SB15がショートされて繋がっているようなのでいちおう
SYS Trace Asynchronous Sw SYS_JTCK-SWCLK PA14
SYS Trace Asynchronous Sw SYS_JTMS-SWDIO PA13
SYS Trace Asynchronous Sw SYS_JTDO-TRACESWO PB3
・SysTickのクロック源はSystemClockで
SYS SysTick SYS_VS_Systick VP_SYS_VS_Systick
ピンラベル(使うのだけ)
Pin Nb PINs FUNCTIONs LABELs
2 PC13 GPIO_EXTI13 B1 [Blue PushButton]
21 PA5 GPIO_Output LD2 [Green Led]
プロジェクト設定
SOFTWARE PROJECT
Project Settings :
Project Name : f303re_led
Project Folder : /Users/mickey/STM32Project/f303re_led
Toolchain / IDE : SW4STM32
Firmware Package Name and Version : STM32Cube FW_F3 V1.6.0
Code Generation Settings :
STM32Cube Firmware Library Package : Copy only the necessary library files
Generate peripheral initialization as a pair of '.c/.h' files per peripheral : No
Backup previously generated files when re-generating : No
Delete previously generated files when not re-generated : Yes
Set all free pins as analog (to optimize the power consumption) : No
手順5.ちょこっとだけコードを追加
main.cの先頭の USER CODE BEGIN 0 〜 USER CODE END 0の間に以下の定義を追加
(NANO-libの初期化処理から呼ばれる)
ついでにテスト用のLチカコード
手順6.makefile
プロジェクトフォルダ直下に、下記の内容でmakefileを作ります。
前回からの変更点は以下になります
・NANO-libをリンク (加えて、-nostartfilesも指定)
・OpenOCDで焼き込みするmakeターゲット(flash)を追加
手順7.ビルド
手順8.書き込み
前提環境
・MacBook Pro (15-inch, Early 2011)
・macOS Sierra バージョン 10.12.2
・make ... たぶんXCodeのコマンドラインツール
・MacPort 2.3.5 ... OpenOCDのビルド
・git ... MacPortでインストール
構築する環境
・launchpad GNU ARM Embedded Toolchain : 5-2016-q3-update
・OpenOCD : ソースからビルド, CMSIS-DAPとSTLinkに対応
・STM32CubeMX : 4.18.0
目標
・CubeMXで雛形を生成
・launchpadのGNU ARM Embedded Toolchainでビルドする
・テキストエディタ+makeで開発
・OpenOCDで書き込み & デバッグする
ターゲット
・Nucleo-F303RE ボード
おっきいボードに変えてみました
・CubeMXで雛形を生成してLチカ
手順1.arm-none-eabi-gccの入手
お手軽にlaunchpadからバイナリを入手します。
右のDownloadsのリストから、gcc-arm-none-eabi-5_4-2016q3-20160926-mac.tar.bz2をダウンロードし、
~/gcc_arm下に展開します。
(makefile使い回しの都合上、展開フォルダ名を変更しました)
$ cd ~ $ tar jxf ~/Downloads/gcc-arm-none-eabi-5_4-2016q3-20160926-mac.tar.bz2 $ mv gcc-arm-none-eabi-5_4-2016q3 gcc-arm
手順2.OpenOCDのビルド
ソースからビルドします
makefile使い回しの都合上、HOMEディレクトリ直下に展開しています。
(Nucleoだけを使う場合はCMSIS-DAPは不要)
$ cd ~ $ sudo port install libtool autoconf texinfo libusb $ sudo port install hidapi-devel $ git clone http://repo.or.cz/r/openocd.git openocd $ cd openocd $ ./bootstrap $ ./configure --enable-stlink --enable-cmsis-dap $ make
手順3.STM32 CubeMXの入手とインストール
STmicroのサイトからダウンロードします。
メールアドレスを入力するとダウンロードURLがメールで送られてきます。
ダウンロードしたファイル(en.stm32cubemx.zip)を展開し、SetupSTM32CubeMX-4.18.0.appを右クリック->開くで起動してインストール、、、
なのですが、理由はよくわかりませんが、Finderからインストーラが起動しません??
ターミナルを開いてzipを展開したフォルダに移動し、下記のようにインストーラを直で起動してインストールしました。
なんなんでしょうね?
$ cd SetupSTM32CubeMX-4.18.0.app/Contents/MacOs/ $ ./SetupSTM32CubeMX-4_18_0_macos
インストールできたらApplicationフォルダからCubeMXを起動し、
[Help]-[Install New Libraries]で必要なMCU用のライブラリ(STM32CubeF3)をインストールします。
手順4.CubeMXでテンプレートを作成
[File]-[New Project...]を選択
[Board Selector]タブに切り替え
[Type of Board]で Nucleo64 を選択
[MCU Series]で STM32F3 を選択
[Boards List]から NUCLEO-F303RETx を選択
ペリフェラルの設定
・HSE外部クロック源 - STLinkからMCOに供給される外部クロック(8MHz)
RCC BYPASS Clock Source RCC_OSC_IN PF0-OSC_IN
・LSE外部クロック源 - Nucleoボードに載っているクリスタル(32.768KHz)
RCC Crystal/Ceramic Resonator RCC_OSC32_IN PC14-OSC32_IN
RCC Crystal/Ceramic Resonator RCC_OSC32_OUT PC15-OSC32_OUT
・SWD : SWOが使えるのかよくわからないけれど、SB15がショートされて繋がっているようなのでいちおう
SYS Trace Asynchronous Sw SYS_JTCK-SWCLK PA14
SYS Trace Asynchronous Sw SYS_JTMS-SWDIO PA13
SYS Trace Asynchronous Sw SYS_JTDO-TRACESWO PB3
・SysTickのクロック源はSystemClockで
SYS SysTick SYS_VS_Systick VP_SYS_VS_Systick
ピンラベル(使うのだけ)
Pin Nb PINs FUNCTIONs LABELs
2 PC13 GPIO_EXTI13 B1 [Blue PushButton]
21 PA5 GPIO_Output LD2 [Green Led]
プロジェクト設定
SOFTWARE PROJECT
Project Settings :
Project Name : f303re_led
Project Folder : /Users/mickey/STM32Project/f303re_led
Toolchain / IDE : SW4STM32
Firmware Package Name and Version : STM32Cube FW_F3 V1.6.0
Code Generation Settings :
STM32Cube Firmware Library Package : Copy only the necessary library files
Generate peripheral initialization as a pair of '.c/.h' files per peripheral : No
Backup previously generated files when re-generating : No
Delete previously generated files when not re-generated : Yes
Set all free pins as analog (to optimize the power consumption) : No
手順5.ちょこっとだけコードを追加
main.cの先頭の USER CODE BEGIN 0 〜 USER CODE END 0の間に以下の定義を追加
(NANO-libの初期化処理から呼ばれる)
/* USER CODE BEGIN 0 */ void _init(void) { } /* USER CODE END 0 */
ついでにテスト用のLチカコード
/* USER CODE BEGIN WHILE */ while (1) { HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, SET); HAL_Delay(1000); HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, RESET); HAL_Delay(1000); /* USER CODE END WHILE */
手順6.makefile
プロジェクトフォルダ直下に、下記の内容でmakefileを作ります。
前回からの変更点は以下になります
・NANO-libをリンク (加えて、-nostartfilesも指定)
・OpenOCDで焼き込みするmakeターゲット(flash)を追加
PROJECT = f303re_led DIR=~/gcc-arm/bin CC=$(DIR)/arm-none-eabi-gcc NM=$(DIR)/arm-none-eabi-nm CP=$(DIR)/arm-none-eabi-objcopy OD=$(DIR)/arm-none-eabi-objdump SZ=$(DIR)/arm-none-eabi-size # SEMIHOST_LIB = --specs=rdimon.specs -lrdimon NANOLIB = --specs=nano.specs OPENOCD=~/openocd BOARDCNF=st_nucleo_f3.cfg DEFS = -DUSE_HAL_DRIVER -DSTM32F303xE MCU = cortex-m4 MCFLAGS = -MD -mcpu=$(MCU) -march=armv7e-m -mtune=$(MCU) MCFLAGS += -mthumb -mlittle-endian -mno-unaligned-access -mno-sched-prolog MCFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 MCFLAGS += -fno-strict-aliasing -fsigned-char MCFLAGS += -ffunction-sections -fdata-sections MCFLAGS += -fno-schedule-insns2 MCFLAGS += -fno-common -fno-hosted MCFLAGS += -mthumb-interwork MCFLAGS += -fmessage-length=0 MCFLAGS += -ffreestanding MCFLAGS += -fno-move-loop-invariants MCFLAGS += -nostartfiles MCFLAGS += -Wl,--gc-sections STM32_INCLUDES = \ -IInc \ -IDrivers/CMSIS/Device/ST/STM32F3xx/Include \ -IDrivers/CMSIS/Include \ -IDrivers/STM32F3xx_HAL_Driver/Inc/Legacy \ -IDrivers/STM32F3xx_HAL_Driver/Inc #OPTIMIZE = -Os OPTIMIZE = -gdwarf-2 -O0 -flto-partition=none -fipa-sra CFLAGS = $(MCFLAGS) $(OPTIMIZE) $(NANOLIB) $(SEMIHOST_LIB) $(DEFS) $(STM32_INCLUDES) CFLAGS += -Wl,-T,STM32F303RETx_FLASH.ld AFLAGS = $(MCFLAGS) CSRC = \ Src/main.c \ Src/stm32f3xx_hal_msp.c \ Src/stm32f3xx_it.c \ Src/system_stm32f3xx.c \ Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal.c \ Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_cortex.c \ Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c \ Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_rcc.c \ Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_rcc_ex.c \ Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_uart.c ASRC = Drivers/CMSIS/Device/ST/STM32F3xx/Source/Templates/gcc/startup_stm32f303xe.s COBJ = $(CSRC:.c=.o) AOBJ = $(ASRC:.s=.o) all: build size build: elf hex lst sym elf: $(PROJECT).elf hex: $(PROJECT).hex lst: $(PROJECT).lst sym: $(PROJECT).sym %.hex: %.elf @echo $(CP) -O ihex $< $@ %.lst: %.elf @echo $(OD) -h -S -C $< > $@ %.sym: %.elf @echo $(NM) -n $< > $@ size: @echo $(SZ) $(PROJECT).hex $(SZ) $(PROJECT).elf $(SZ) -A -x $(PROJECT).elf %.elf: $(AOBJ) $(COBJ) @echo $(CC) $(CFLAGS) $^ -o $@ $(COBJ) : %.o : %.c @echo $(CC) -c $(CFLAGS) $< -o $@ $(AOBJ) : %.o : %.s @echo $(CC) -c $(CFLAGS) $< -o $@ clean: @echo find . -name '*.o' -print -or -name '*.d' -print | xargs rm -f rm -f $(PROJECT).elf $(PROJECT).hex $(PROJECT).lst $(PROJECT).sym flash: $(PROJECT).elf $(OPENOCD)/src/openocd -s $(OPENOCD)/tcl -f board/$(BOARDCNF) -c "program $^ verify reset exit"
手順7.ビルド
$ make
手順8.書き込み
$ make flash
トラ技ARM基板をCMSIS-DAPにしてOpenOCDを使ってお中華STMボードをどうこうするテスト [電子工作]
約$2で送料無料、日本のAmazonでも290円というおおよそあたまがおかしいんじゃないかという価格で売られているSTM32F103C8T6搭載ボードを買ってみました。
ついでに、昔買ったきり放置していたトラ技ARM基板をCMSIS-DAPにして
OpenOCDからどうこうする環境を作ってテストしてみました。
※ぶっちゃけ、デバッガに関しては秋月からSTLink/V2を買ったほうが安いんですがw
OpenOCDをCMSIS-DAPを有効にしてビルド
※Nucleoボードも使うので、STLinkも有効にしてます
Macの場合
$ sudo port install libtool autoconf texinfo libusb $ sudo port install hidapi-devel $ git clone http://repo.or.cz/r/openocd.git openocd $ cd openocd $ ./bootstrap $ ./configure --enable-stlink --enable-cmsis-dap $ make -j4
Ubuntuの場合
hidapiライブラリの名前がlibhidapi-devになります。
$ sudo apt-get install libtool autoconf texinfo libusb $ sudo apt-get install libhidapi-dev $ git clone http://repo.or.cz/r/openocd.git openocd $ cd openocd $ ./bootstrap $ ./configure --enable-stlink --enable-cmsis-dap $ make
Ubuntuの場合は以下のudevルールの追加が必要です
$ cat /etc/udev/rules.d/99-CMSIS.rules # CMSIS-DAP compatible adapters ATTRS{product}=="*CMSIS-DAP*", MODE="664", GROUP="plugdev"
※参考:STLink用のudevルール
$ cat /etc/udev/rules.d/99-stlink.rules # STLink v1 ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3744", MODE="664", GROUP="plugdev" # STLink v2 ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", MODE="664", GROUP="plugdev" # STLink v2-1 ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", MODE="664", GROUP="plugdev"
※以下はhidapiのソースを取ってきてビルドする手順
$ sudo apt-get install libudev-dev $ git clone git://github.com/signal11/hidapi.git $ cd hidapi $ ./bootstrap $ ./configure $ make $ sudo make install $ sudo ln -s /usr/local/lib/libhidapi-hidraw.so.0 /usr/lib/libhidapi-hidraw.so.0
トラ技ARM基板 -> 中華STM32基板
※トラ技ARM基板には、雑誌付属のCD-ROM、またはトラ技HomePageからCMSIS-DAPファームウェアを書き込んでおく。
中華STM32基板とトラ技ARM基板との3.3V, GND, SWDIO, SWCLKを接続し、
トラ技ARM基板にUSBで接続
$ cd tcl $ ../src/openocd -f interface/cmsis-dap.cfg -f target/stm32f1x.cfg
を、いい感じですね。
適当なバイナリを書き込んでみましょう
速度もまあまあでしょうか?
ところで、HALドライバのデバイスの定義で、F103C8が無くってF103C6とCBしかないのが
紛らわしくて困りました。
C8とCBの違いはFLASHサイズだけのようなので、CBの定義を使っておけばいいんでしょうけど…
STM32 ComparatorのイベントでTimerのInput Captureにトリガするには? [電子工作]
CubeMXで構成できないか調べているところですが、
COMPx
Configurationで[Output Parameters] -> [Output Internal Selection]で
"Timer x Input Capture x"を指定
TIMx
上記でしていしたTimerのChannelについて、"Input Capture direct mode"を指定
ここで問題。
CubeMXでは"Input Capture direct mode"を指定すると、必ずTIMx_CHxの入力ピンを構成してしまう模様。
なのでTIMx_CHxの入力ピンが空いていないとCubeMXでは構成できない?
とりあえず、TimerのChannel設定無しでコードを生成してから
下記のコードをMX_TIMx_Init()の関数に差し込めばTIMx_CHxのピンを使わずに
COMP -> TIMのInputCaptureへの接続ができそう。
(下記の例は TIM3 Channel3にCOMPからのイベントを接続)
COMPx
Configurationで[Output Parameters] -> [Output Internal Selection]で
"Timer x Input Capture x"を指定
TIMx
上記でしていしたTimerのChannelについて、"Input Capture direct mode"を指定
ここで問題。
CubeMXでは"Input Capture direct mode"を指定すると、必ずTIMx_CHxの入力ピンを構成してしまう模様。
なのでTIMx_CHxの入力ピンが空いていないとCubeMXでは構成できない?
とりあえず、TimerのChannel設定無しでコードを生成してから
下記のコードをMX_TIMx_Init()の関数に差し込めばTIMx_CHxのピンを使わずに
COMP -> TIMのInputCaptureへの接続ができそう。
(下記の例は TIM3 Channel3にCOMPからのイベントを接続)
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; sConfigIC.ICFilter = 0; if (HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_3) != HAL_OK) { Error_Handler(); }
VirtualBoxのUbuntuにgnu arm embedded toolchain + OpenOCDでSTM32の開発環境を作る [電子工作]
開発環境をUbuntuに変更しました。
今回は、STM32CubeMXから出力したプロジェクトフォルダを「そのまま」でビルドを目指します。
環境
・MacBook Pro (15-inch, Early 2011) (16GB RAM + 1TB SSD)
・macOS Sierra バージョン 10.12.1
・VirtualBox 5.0.28
・Ubuntu 16.04 LTS 日本語Remix (4GB RAM + 2Core割り当て)
目標
・テキストエディタ+makeで開発
・launchpadのGNU ARM Embedded Toolchainでビルドする
・OpenOCDで書き込み & デバッグする
ターゲット
・Nucleo-F303K8 ボード
・STM32CubeMXのプロジェクトをそのままビルドするMakefileを書く!
それでは手順開始です。
0.ダウンロードフォルダのシンボリックリンクを作る
Firefoxでダウンロードするときのフォルダ名が「ダウンロード」とコマンドから使いづらいので、
シンボリックリンクを作っておきます。
1.arm-none-eabi-gccの入手
お手軽にlaunchpadからバイナリを入手します。
右のDownloadsのリストから、gcc-arm-none-eabi-5_4-2016q3-20160926-linux.tar.bz2をダウンロードし、HOME直下に展開します。
makefileから参照するために、フォルダ名からバージョン番号を外しておきます。
とりあえず、pathは通さないでおきます。
2.OpenOCDの入手とインストール
今回はgitリポジトリから最新版のソースを持ってきて自前でビルドしてみます。
ビルドに必要なパッケージをインストール
gitからソースツリーを入手
あとはビルドするだけ
USB接続のST-LinkをOSで認識するようにudevルールを設定します。
contrib/99-openocd.rulesから、ST-Link V2.1の設定を抜き出して設定しました。
(このファイルをそのまま設定しちゃってもいいような気もしますが)
Nucleoボードを接続して動作を確認してみましょう。
VirtualBoxの方で、ST-Linkのデバイスを仮想マシンに回すように設定します。
MacBookにNucleoボードを接続し、VirtualBoxの仮想マシンの設定で、ポート - USBを選択
追加アイコンをクリックして、STM32 STLinkを追加
MacBookから一度Nucleoボードを取り外して再度接続すると、仮想マシン側で認識します。
接続を確認してみます。
このように出力され、NucleoボードのLEDが赤と緑に点滅すれば成功です。
確認したら、Ctrl-CでOpenOCDを終了させてボードを外しておきましょう。
3.STM32CubeMXのインストール
まずJava JREをインストールします。
OpenJDK版でもいいような気もしますが、Oracle版を入れてみます。
Oracleのサイトから、Linux x64のアーカイブをダウンロード
以下の手順でインストールします。
JREをインストール後、JAVA_HOMEをユーザーのプロファイルに設定しておきます。
.bashrcの末尾に以下を追記
STMicroのサイトから、STM32CubeMXをダウンロードして展開
ここで、インストーラを実行するために、32ビット用のライブラリが必要になります。
最初はこれがわからずにえらいハマった…
インストーラを実行
デフォルト設定でインストールします。
インストールできたら、STM32CubeMXを実行
Help - Install New Librariesで、STM32F3のFirmware Packageをダウンロードします。
4.STM32CubeMXでプロジェクト作成
とりあえず、Lチカさせてみましょう。
STM32CubeMXを起動してNew Projectをクリック
Board Selectorタブで、NUCLEO-F303K8を選択
このボードではPB3がLED3に接続されているので、PinoutのタブでPB3のピン設定をGPIO_Outputに設定
ConfigurationのタブでGPIOを選択し
User Labelに「LED3」の名前をつけておきます。
こうすることで、コードからはGPIO_ほにゃらら_LED3でピン設定できるようになります。
Project - Settingで出力先と、使用するToolchainを選択します。
Toolchainには、必ずSW4STM32を選択するようにしてください。
Project - Generate Codeでコードを生成
生成されたフォルダで、makefileを作成します。
Srcフォルダに_exit.cも足しましょう
どっかに、いい_exit.cないですかねえ?
Src/main.cを編集して、Lチカコードを書きます。
User Labelをつけたので、実際のピン番号(PB3)を気にせず書けます。
生成されたコードのあちこにに埋め込まれている、「USER CODE BEGIN」〜「USER CODE END」の
間にコードを書くと、書いたコードを残したままで、後でCubeMXでコードを生成しなおせます。
ビルド
ビルドできましたか?
make flashで、OpenOCDで焼き込みできるようにしてあります。
LEDが点滅すれば成功です!
今回は、STM32CubeMXから出力したプロジェクトフォルダを「そのまま」でビルドを目指します。
環境
・MacBook Pro (15-inch, Early 2011) (16GB RAM + 1TB SSD)
・macOS Sierra バージョン 10.12.1
・VirtualBox 5.0.28
・Ubuntu 16.04 LTS 日本語Remix (4GB RAM + 2Core割り当て)
目標
・テキストエディタ+makeで開発
・launchpadのGNU ARM Embedded Toolchainでビルドする
・OpenOCDで書き込み & デバッグする
ターゲット
・Nucleo-F303K8 ボード
・STM32CubeMXのプロジェクトをそのままビルドするMakefileを書く!
それでは手順開始です。
0.ダウンロードフォルダのシンボリックリンクを作る
Firefoxでダウンロードするときのフォルダ名が「ダウンロード」とコマンドから使いづらいので、
シンボリックリンクを作っておきます。
cd ~ ln -s ダウンロード downloads
1.arm-none-eabi-gccの入手
お手軽にlaunchpadからバイナリを入手します。
右のDownloadsのリストから、gcc-arm-none-eabi-5_4-2016q3-20160926-linux.tar.bz2をダウンロードし、HOME直下に展開します。
makefileから参照するために、フォルダ名からバージョン番号を外しておきます。
$ cd ~ $ tar jxf ~/downloads/gcc-arm-none-eabi-5_4-2016q3-20160926-linux.tar.bz2 $ mv gcc-arm-none-eabi-5_4-2016q3 gcc-arm
とりあえず、pathは通さないでおきます。
2.OpenOCDの入手とインストール
今回はgitリポジトリから最新版のソースを持ってきて自前でビルドしてみます。
ビルドに必要なパッケージをインストール
$ sudo apt-get install git $ sudo apt-get install libtool autoconf $ sudo apt-get install texinfo $ sudo apt-get install libusb-1.0-0-dev
gitからソースツリーを入手
$ cd ~ $ git clone http://repo.or.cz/r/openocd.git openocd
あとはビルドするだけ
$ cd openocd $ ./bootstrap $ ./configure --enable-stlink $ make -j2
USB接続のST-LinkをOSで認識するようにudevルールを設定します。
contrib/99-openocd.rulesから、ST-Link V2.1の設定を抜き出して設定しました。
(このファイルをそのまま設定しちゃってもいいような気もしますが)
$ grep 374b contrib/99-openocd.rules > 99-stlink.rules $ cat 99-stlink.rules ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", MODE="664", GROUP="plugdev" $ sudo cp 99-stlink.rules /etc/udev/rules.d/ $ sudo service udev restart
Nucleoボードを接続して動作を確認してみましょう。
VirtualBoxの方で、ST-Linkのデバイスを仮想マシンに回すように設定します。
MacBookにNucleoボードを接続し、VirtualBoxの仮想マシンの設定で、ポート - USBを選択
追加アイコンをクリックして、STM32 STLinkを追加
MacBookから一度Nucleoボードを取り外して再度接続すると、仮想マシン側で認識します。
接続を確認してみます。
$ cd ~/openocd/tcl $ ../src/openocd -f board/st_nucleo_f3.cfg Open On-Chip Debugger 0.10.0-dev-00419-gbcaf775 (2016-11-19-09:01) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html adapter speed: 1000 kHz adapter_nsrst_delay: 100 Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD none separate srst_only separate srst_nogate srst_open_drain connect_deassert_srst Info : Unable to match requested speed 1000 kHz, using 950 kHz Info : Unable to match requested speed 1000 kHz, using 950 kHz Info : clock speed 950 kHz Info : STLINK v2 JTAG v28 API v2 SWIM v16 VID 0x0483 PID 0x374B Info : using stlink api v2 Info : Target voltage: 3.252528 Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints
このように出力され、NucleoボードのLEDが赤と緑に点滅すれば成功です。
確認したら、Ctrl-CでOpenOCDを終了させてボードを外しておきましょう。
3.STM32CubeMXのインストール
まずJava JREをインストールします。
OpenJDK版でもいいような気もしますが、Oracle版を入れてみます。
Oracleのサイトから、Linux x64のアーカイブをダウンロード
以下の手順でインストールします。
$ sudo mkdir -p /usr/lib/jvm $ sudo tar zxf ~/downloads/jre-8u112-linux-x64.tar.gz -C /usr/lib/jvm $ sudo update-alternatives --install "/usr/bin/java" "java" "/usr/lib/jvm/jre1.8.0_112/bin/java" 1 $ sudo update-alternatives --set java /usr/lib/jvm/jre1.8.0_112/bin/java $ java -version
JREをインストール後、JAVA_HOMEをユーザーのプロファイルに設定しておきます。
.bashrcの末尾に以下を追記
export JAVA_HOME=/usr/lib/jvm/jre1.8.0_112
STMicroのサイトから、STM32CubeMXをダウンロードして展開
$ cd ~/downloads $ unzip en.stm32cubemx.zip
ここで、インストーラを実行するために、32ビット用のライブラリが必要になります。
最初はこれがわからずにえらいハマった…
$ sudo dpkg --add-architecture i386 $ sudo apt-get update $ sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386
インストーラを実行
デフォルト設定でインストールします。
インストールできたら、STM32CubeMXを実行
Help - Install New Librariesで、STM32F3のFirmware Packageをダウンロードします。
4.STM32CubeMXでプロジェクト作成
とりあえず、Lチカさせてみましょう。
STM32CubeMXを起動してNew Projectをクリック
Board Selectorタブで、NUCLEO-F303K8を選択
このボードではPB3がLED3に接続されているので、PinoutのタブでPB3のピン設定をGPIO_Outputに設定
ConfigurationのタブでGPIOを選択し
User Labelに「LED3」の名前をつけておきます。
こうすることで、コードからはGPIO_ほにゃらら_LED3でピン設定できるようになります。
Project - Settingで出力先と、使用するToolchainを選択します。
Toolchainには、必ずSW4STM32を選択するようにしてください。
Project - Generate Codeでコードを生成
生成されたフォルダで、makefileを作成します。
PROJECT = nucleof303k8_led DIR=~/gcc-arm/bin CC=$(DIR)/arm-none-eabi-gcc NM=$(DIR)/arm-none-eabi-nm CP=$(DIR)/arm-none-eabi-objcopy OD=$(DIR)/arm-none-eabi-objdump SZ=$(DIR)/arm-none-eabi-size OPENOCD=~/openocd BOARDCNF=st_nucleo_f3.cfg DEFS = -DUSE_HAL_DRIVER -DSTM32F303x8 MCU = cortex-m4 MCFLAGS = -MD -mcpu=$(MCU) -march=armv7e-m -mtune=$(MCU) MCFLAGS += -mthumb -mlittle-endian -mno-unaligned-access -mno-sched-prolog MCFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 MCFLAGS += -fno-strict-aliasing -fsigned-char MCFLAGS += -ffunction-sections -fdata-sections MCFLAGS += -fno-schedule-insns2 MCFLAGS += -fno-common -fno-hosted MCFLAGS += -mthumb-interwork MCFLAGS += -fmessage-length=0 MCFLAGS += -ffreestanding MCFLAGS += -fno-move-loop-invariants MCFLAGS += -Wl,--gc-sections STM32_INCLUDES = \ -IInc \ -IDrivers/CMSIS/Device/ST/STM32F3xx/Include \ -IDrivers/CMSIS/Include \ -IDrivers/STM32F3xx_HAL_Driver/Inc/Legacy \ -IDrivers/STM32F3xx_HAL_Driver/Inc #OPTIMIZE = -Os OPTIMIZE = -gdwarf-2 -O0 -flto-partition=none -fipa-sra CFLAGS = $(MCFLAGS) $(OPTIMIZE) $(DEFS) $(STM32_INCLUDES) CFLAGS += -Wl,-T,STM32F303K8Tx_FLASH.ld AFLAGS = $(MCFLAGS) CSRC = \ Src/main.c \ Src/stm32f3xx_it.c \ Drivers/CMSIS/Device/ST/STM32F3xx/Source/Templates/system_stm32f3xx.c \ Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal.c \ Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_cortex.c \ Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_rcc.c \ Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c \ Src/_exit.c ASRC = Drivers/CMSIS/Device/ST/STM32F3xx/Source/Templates/gcc/startup_stm32f303x8.s COBJ = $(CSRC:.c=.o) AOBJ = $(ASRC:.s=.o) all: build size build: elf hex lst sym elf: $(PROJECT).elf hex: $(PROJECT).hex lst: $(PROJECT).lst sym: $(PROJECT).sym %.hex: %.elf @echo $(CP) -O ihex $< $@ %.lst: %.elf @echo $(OD) -h -S -C $< > $@ %.sym: %.elf @echo $(NM) -n $< > $@ size: @echo $(SZ) $(PROJECT).hex $(SZ) $(PROJECT).elf $(SZ) -A -x $(PROJECT).elf %.elf: $(AOBJ) $(COBJ) @echo $(CC) $(CFLAGS) $^ -o $@ $(COBJ) : %.o : %.c @echo $(CC) -c $(CFLAGS) $< -o $@ $(AOBJ) : %.o : %.s @echo $(CC) -c $(CFLAGS) $< -o $@ clean: @echo find . -name '*.o' -print -or -name '*.d' -print | xargs rm -f rm -f $(PROJECT).elf $(PROJECT).hex $(PROJECT).lst $(PROJECT).sym flash: $(PROJECT).elf $(OPENOCD)/src/openocd -s $(OPENOCD)/tcl -f board/$(BOARDCNF) -c "program $^ verify reset exit"
Srcフォルダに_exit.cも足しましょう
どっかに、いい_exit.cないですかねえ?
Src/main.cを編集して、Lチカコードを書きます。
User Labelをつけたので、実際のピン番号(PB3)を気にせず書けます。
生成されたコードのあちこにに埋め込まれている、「USER CODE BEGIN」〜「USER CODE END」の
間にコードを書くと、書いたコードを残したままで、後でCubeMXでコードを生成しなおせます。
ビルド
$ make
ビルドできましたか?
make flashで、OpenOCDで焼き込みできるようにしてあります。
$ make flash
LEDが点滅すれば成功です!
タグ:STM32
[電子工作] MacでSTM32の開発環境を GNU arm + OpenOCDで作ってみる [電子工作]
ようやくビルド+書き込みが出来るようになったレベルですが、まとめておきます。
-> CubeMXで生成したプロジェクトのビルドはこちら
環境
・MacBook Pro (15-inch, Early 2011) (いい加減古い…)
・macOS Sierra バージョン 10.12.1
・make … たぶんXCodeのコマンドラインツール。
目標
・テキストエディタ+makeで開発
・launchpadのGNU ARM Embedded Toolchainでビルドする
・OpenOCDで書き込み & デバッグする
ターゲット
・Nucleo-F303K8 ボード
単品で同じ石を秋月で買えるから、という理由で選びましたが、ちょっと使いづらいかも
・STM32CubeF3 Firmware PackageのExampleのGPIO_IOToggleをビルドし実行する
いわゆるLチカ
それでは手順開始です。
1.arm-none-eabi-gccの入手
お手軽にlaunchpadからバイナリを入手します。
右のDownloadsのリストから、gcc-arm-none-eabi-5_4-2016q3-20160926-mac.tar.bz2をダウンロードし、~/STM32Toolchain下に展開します。
(展開先は適当)
とりあえず、pathは通さないでおきます。
2.OpenOCDの入手とインストール
こちらもお手軽に、GNU ARM Eclipse OpenOCDのインストールパッケージで入れてしまいます。
githubからインストールパッケージを入手します。
Downloadsのリストから、gnuarmeclipse-openocd-osx-0.10.0-201610281609-dev.pkgをダウンロードし、実行します。
インストール先は、/Applications/GNU ARM Eclipse/OpenOCD になっています。
3.STM32 HAL Driverの入手
STmicroのサイトから、ターゲットのCPUに合わせたドライバをダウンロードします。
今回はSTM32F30xシリーズなので、STM32CubeF3をダウンロードします。
メールアドレスなどの入力が必要ですが、いくつかの手順を経るとen.stm32cubef3.zipというファイルとしてダウンロードできます。
これも、~/STM32Toolchain下に展開します。
4.プロジェクトのひな形を作成
プロジェクトフォルダとして、~/STM32ProjectフォルダにNucleo_F303K8_sample_gpioフォルダを作成します。
作成したフォルダに、STM32CubeF3を展開したフォルダから、Driversフォルダをまるごとごっそりコピーします。
5.サンプルのコードをコピー
STM32CubeF3を展開したフォルダから、Projects/STM32F303K8-Nucleo/Examples/GPIO/GPIO_IOToggleフォルダの、SrcとIncとSW4STM32フォルダをコピーします。
6.makefileを準備
プロジェクトフォルダ直下に、下記の内容でmakefileを作ります。
※コンパイルフラグはよくわからずに書いているものもあるのでもう少し煮詰めたほうが良いような気はしています。
※HAL Driverのソースは、ビルドしながら必要なものを集めました。
makeしてみましょう。
_exitが無いと怒られてしまいました。
たぶん空関数で良いと思うので、適当に作ってSrcフォルダに突っ込みます。
_exit.c
makefileのビルド対象にも加えて、再ビルド。
sample.elfファイルが生成されれば成功です。
-> CubeMXで生成したプロジェクトのビルドはこちら
環境
・MacBook Pro (15-inch, Early 2011) (いい加減古い…)
・macOS Sierra バージョン 10.12.1
・make … たぶんXCodeのコマンドラインツール。
目標
・テキストエディタ+makeで開発
・launchpadのGNU ARM Embedded Toolchainでビルドする
・OpenOCDで書き込み & デバッグする
ターゲット
・Nucleo-F303K8 ボード
単品で同じ石を秋月で買えるから、という理由で選びましたが、ちょっと使いづらいかも
・STM32CubeF3 Firmware PackageのExampleのGPIO_IOToggleをビルドし実行する
いわゆるLチカ
それでは手順開始です。
1.arm-none-eabi-gccの入手
お手軽にlaunchpadからバイナリを入手します。
右のDownloadsのリストから、gcc-arm-none-eabi-5_4-2016q3-20160926-mac.tar.bz2をダウンロードし、~/STM32Toolchain下に展開します。
(展開先は適当)
cd ~ mkdir STM32Toolchain cd STM32Toolchain tar jxf ~/Downloads/gcc-arm-none-eabi-5_4-2016q3-20160926-mac.tar.bz2
とりあえず、pathは通さないでおきます。
2.OpenOCDの入手とインストール
こちらもお手軽に、GNU ARM Eclipse OpenOCDのインストールパッケージで入れてしまいます。
githubからインストールパッケージを入手します。
Downloadsのリストから、gnuarmeclipse-openocd-osx-0.10.0-201610281609-dev.pkgをダウンロードし、実行します。
インストール先は、/Applications/GNU ARM Eclipse/OpenOCD になっています。
3.STM32 HAL Driverの入手
STmicroのサイトから、ターゲットのCPUに合わせたドライバをダウンロードします。
今回はSTM32F30xシリーズなので、STM32CubeF3をダウンロードします。
メールアドレスなどの入力が必要ですが、いくつかの手順を経るとen.stm32cubef3.zipというファイルとしてダウンロードできます。
これも、~/STM32Toolchain下に展開します。
cd ~/STM32Toolchain unzip ~/Downloads/en.stm32cubef3.zip
4.プロジェクトのひな形を作成
プロジェクトフォルダとして、~/STM32ProjectフォルダにNucleo_F303K8_sample_gpioフォルダを作成します。
cd ~ mkdir -p STM32Project/Nucleo_F303K8_sample_gpio
作成したフォルダに、STM32CubeF3を展開したフォルダから、Driversフォルダをまるごとごっそりコピーします。
cd ~/STM32Project/Nucleo_F303K8_sample_gpio cp -a ~/STM32Toolchain/STM32Cube_FW_F3_V1.6.0/Drivers .
5.サンプルのコードをコピー
STM32CubeF3を展開したフォルダから、Projects/STM32F303K8-Nucleo/Examples/GPIO/GPIO_IOToggleフォルダの、SrcとIncとSW4STM32フォルダをコピーします。
cd ~/STM32Project/Nucleo_F303K8_sample_gpio cp -a ~/STM32Toolchain/STM32Cube_FW_F3_V1.6.0/Projects/STM32F303K8-Nucleo/Examples/GPIO/GPIO_IOToggle/Src . cp -a ~/STM32Toolchain/STM32Cube_FW_F3_V1.6.0/Projects/STM32F303K8-Nucleo/Examples/GPIO/GPIO_IOToggle/Inc . cp -a ~/STM32Toolchain/STM32Cube_FW_F3_V1.6.0/Projects/STM32F303K8-Nucleo/Examples/GPIO/GPIO_IOToggle/SW4STM32 .
6.makefileを準備
プロジェクトフォルダ直下に、下記の内容でmakefileを作ります。
※コンパイルフラグはよくわからずに書いているものもあるのでもう少し煮詰めたほうが良いような気はしています。
※HAL Driverのソースは、ビルドしながら必要なものを集めました。
PROJECT = sample DIR=~/STM32Toolchain/gcc-arm-none-eabi-5_4-2016q3/bin CC=$(DIR)/arm-none-eabi-gcc NM=$(DIR)/arm-none-eabi-nm CP=$(DIR)/arm-none-eabi-objcopy OD=$(DIR)/arm-none-eabi-objdump SZ=$(DIR)/arm-none-eabi-size DEFS = -DUSE_HAL_DRIVER -DSTM32F303x8 MCU = cortex-m4 MCFLAGS = -MD -mcpu=$(MCU) -march=armv7e-m -mtune=$(MCU) MCFLAGS += -mthumb -mlittle-endian -mno-unaligned-access -mno-sched-prolog MCFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 MCFLAGS += -fno-strict-aliasing -fsigned-char MCFLAGS += -ffunction-sections -fdata-sections MCFLAGS += -fno-schedule-insns2 MCFLAGS += -fno-common -fno-hosted MCFLAGS += -mthumb-interwork MCFLAGS += -fmessage-length=0 MCFLAGS += -ffreestanding MCFLAGS += -fno-move-loop-invariants STM32_INCLUDES = -IInc \ -IDrivers/BSP/STM32F3xx_Nucleo_32 \ -IDrivers/CMSIS/Device/ST/STM32F3xx/Include \ -IDrivers/CMSIS/Include \ -IDrivers/STM32F3xx_HAL_Driver/Inc/Legacy \ -IDrivers/STM32F3xx_HAL_Driver/Inc #OPTIMIZE = -Os OPTIMIZE = -gdwarf-2 -O0 -flto-partition=none -fipa-sra CFLAGS = $(MCFLAGS) $(OPTIMIZE) $(DEFS) $(STM32_INCLUDES) CFLAGS += -Wl,-T,SW4STM32/STM32F303K8_NUCLEO/STM32F303K8Tx_FLASH.ld AFLAGS = $(MCFLAGS) SRC = Src/main.c \ Src/stm32f3xx_it.c \ Src/system_stm32f3xx.c \ Drivers/BSP/STM32F3xx_Nucleo_32/stm32f3xx_nucleo_32.c \ Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal.c \ Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_cortex.c \ Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_rcc.c \ Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c ASRC = SW4STM32/startup_stm32f303x8.s COBJ = $(SRC:.c=.o) AOBJ = $(ASRC:.s=.o) all: build size build: elf hex lst sym elf: $(PROJECT).elf hex: $(PROJECT).hex lst: $(PROJECT).lst sym: $(PROJECT).sym %.hex: %.elf @echo $(CP) -O ihex $< $@ %.lst: %.elf @echo $(OD) -h -S -C $< > $@ %.sym: %.elf @echo $(NM) -n $< > $@ size: @echo $(SZ) $(PROJECT).hex $(SZ) $(PROJECT).elf $(SZ) -A -x $(PROJECT).elf %.elf: $(AOBJ) $(COBJ) @echo $(CC) $(CFLAGS) $^ -o $@ $(COBJ) : %.o : %.c @echo $(CC) -c $(CFLAGS) $< -o $@ $(AOBJ) : %.o : %.s @echo $(CC) -c $(CFLAGS) $< -o $@ clean: @echo find . -name '*.o' -print | xargs rm rm $(PROJECT).elf $(PROJECT).hex $(PROJECT).lst $(PROJECT).sym
makeしてみましょう。
/Users/user/STM32Toolchain/gcc-arm-none-eabi-5_4-2016q3/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/lib/armv7e-m/fpu/libc.a(lib_a-exit.o): In function `exit': exit.c:(.text.exit+0x16): undefined reference to `_exit' collect2: error: ld returned 1 exit status make: *** [sample.elf] Error 1
_exitが無いと怒られてしまいました。
たぶん空関数で良いと思うので、適当に作ってSrcフォルダに突っ込みます。
_exit.c
void __attribute__((weak)) _exit(int code __attribute__((unused))) { // TODO: write on trace while (1) ; }
makefileのビルド対象にも加えて、再ビルド。
SRC = Src/main.c \ Src/stm32f3xx_it.c \ Src/system_stm32f3xx.c \ Drivers/BSP/STM32F3xx_Nucleo_32/stm32f3xx_nucleo_32.c \ Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal.c \ Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_cortex.c \ Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_rcc.c \ Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c \ Src/_exit.c
sample.elfファイルが生成されれば成功です。
タグ:STM32 STM32F303K8
[電子工作] ATxmega (E series)でFatFsをDMA対応する - rcvr_spi_milti関数 - [電子工作]
いよいよ本丸です。
いきなりコードから。
(E)DMAの使い方は、
1. 転送元アドレスを設定
2. 転送先アドレスを設定
3. 転送条件(開始トリガ)を設定
4. 完了を待つ
が基本のようです。
3.の転送条件について様々なペリフェラルの状態を設定できます。
今回はUSARTのSPIマスタモードの転送なので、それに合わせて設定することになります。
SPI転送には「送信処理」と「受信処理」の両方が必要になります。
DMAは片方向の転送処理なので、「送信DMA動作」と「受信DMA動作」の2つのchannelを使うことになります。
今回は Channel0 -> 受信動作, Channel2 -> 送信動作 に割り当てています。
1バイトの受信(転送)処理とDMA転送との対応は下記のようになります。
ここで一点、注意が。
ねむいさんのブログにも書かれていましたが、DMAを起動する際に受信側を先に起動する必要があるようです。
(合わせてDMAの優先度も受信側が優先度高にしたほうが良い?)
理由はよくわからないのですが、逆にするとDMA転送しなくなることがありました。
これ、本家Application Noteに書いといてほしいですね…
いきなりコードから。
/* Receive a data block fast */ static void rcvr_spi_multi ( BYTE *p, /* Data read buffer */ UINT cnt /* Size of data block */ ) { volatile uint8_t dmy = 0xff; /* DMA Chennel0 -> Transfer from USARTD0.Data to buffer */ EDMA.CH0.ADDRCTRL = EDMA_CH_RELOAD_NONE_gc | EDMA_CH_DIR_FIXED_gc; EDMA.CH0.DESTADDRCTRL = EDMA_CH_RELOAD_NONE_gc | EDMA_CH_DIR_INC_gc; EDMA.CH0.TRIGSRC = EDMA_CH_TRIGSRC_USARTD0_RXC_gc; EDMA.CH0.ADDRL = (uint16_t)(&USARTD0.DATA) & 0xff; EDMA.CH0.ADDRH = ((uint16_t)(&USARTD0.DATA) >> 8) & 0xff; EDMA.CH0.DESTADDRL = (uint16_t)p & 0xff; EDMA.CH0.DESTADDRH = ((uint16_t)p >> 8) & 0xff; EDMA.CH0.TRFCNTL = cnt & 0xff; EDMA.CH0.TRFCNTH = (cnt >> 8) & 0xff; /* DMA Chennel2 -> Transfer dummy 0xff to USARTD0.Data */ EDMA.CH2.ADDRCTRL = EDMA_CH_RELOAD_NONE_gc | EDMA_CH_DIR_FIXED_gc; EDMA.CH2.DESTADDRCTRL = EDMA_CH_RELOAD_NONE_gc | EDMA_CH_DIR_FIXED_gc; EDMA.CH2.TRIGSRC = EDMA_CH_TRIGSRC_USARTD0_DRE_gc; EDMA.CH2.ADDRL = (uint16_t)(&dmy) & 0xff; EDMA.CH2.ADDRH = ((uint16_t)(&dmy) >> 8) & 0xff; EDMA.CH2.DESTADDRL = (uint16_t)(&USARTD0.DATA) & 0xff; EDMA.CH2.DESTADDRH = ((uint16_t)(&USARTD0.DATA) >> 8) & 0xff; EDMA.CH2.TRFCNTL = cnt & 0xff; EDMA.CH2.TRFCNTH = (cnt >> 8) & 0xff; /* To make stable transmission, Rx must be enaled first ! */ EDMA.CH0.CTRLA = EDMA_CH_ENABLE_bm | EDMA_CH_SINGLE_bm; EDMA.CH2.CTRLA = EDMA_CH_ENABLE_bm | EDMA_CH_SINGLE_bm; while ( !(EDMA.INTFLAGS & EDMA_CH0TRNFIF_bm) ) {} EDMA.INTFLAGS |= EDMA_CH0TRNFIF_bm | EDMA_CH2TRNFIF_bm; }
(E)DMAの使い方は、
1. 転送元アドレスを設定
2. 転送先アドレスを設定
3. 転送条件(開始トリガ)を設定
4. 完了を待つ
が基本のようです。
3.の転送条件について様々なペリフェラルの状態を設定できます。
今回はUSARTのSPIマスタモードの転送なので、それに合わせて設定することになります。
SPI転送には「送信処理」と「受信処理」の両方が必要になります。
DMAは片方向の転送処理なので、「送信DMA動作」と「受信DMA動作」の2つのchannelを使うことになります。
今回は Channel0 -> 受信動作, Channel2 -> 送信動作 に割り当てています。
1バイトの受信(転送)処理とDMA転送との対応は下記のようになります。
/* Exchange a byte */ static BYTE xchg_spi ( /* Returns received data */ BYTE dat /* Data to be sent */ ) { /* 送信処理 => データ受信時は、ダミーで0xffを送る! => DMA Channel2に割り当て */ /* 送信可能を待つ => DMAでは「EDMA_CH_TRIGSRC_USARTD0_DRE_gc」条件 */ while ( !(USARTD0.STATUS & USART_DREIF_bm)); USARTD0.DATA = dat; /* データを送信 */ /* 受信処理 => DMA Channel0に割り当て*/ /* 受信完了を待つ => DMAでは「EDMA_CH_TRIGSRC_USARTD0_RXC_gc」条件 */ while ( !(USARTD0.STATUS & USART_RXCIF_bm)); return USARTD0.DATA; /* 受信データを読む */ }
ここで一点、注意が。
/* To make stable transmission, Rx must be enaled first ! */ EDMA.CH0.CTRLA = EDMA_CH_ENABLE_bm | EDMA_CH_SINGLE_bm; EDMA.CH2.CTRLA = EDMA_CH_ENABLE_bm | EDMA_CH_SINGLE_bm;
ねむいさんのブログにも書かれていましたが、DMAを起動する際に受信側を先に起動する必要があるようです。
(合わせてDMAの優先度も受信側が優先度高にしたほうが良い?)
理由はよくわからないのですが、逆にするとDMA転送しなくなることがありました。
これ、本家Application Noteに書いといてほしいですね…