[STM32メモ]uVisionでSTM32CubeMXのUSBミドルウェアを利用する


Keil社はSTM32F0,L0,G0マイコン向けにMDK(統合開発環境やソフトウェアパッケージ群一式)をフリーで提供してくれている。ゼロから何でも作れる人でない限り、こうした環境とパッケージの一式があることは助かる。

ただ、STM32CubeMXが提供するUSBミドルウェアをuVisionで使おうとしたところで嵌まってしまったので、調べたことをまとめる。

つまづいたこと

STM32向けMDKはいくつかのソフトウェアパッケージが利用できない。例えばUSBデバイスのミドルウェア群は"Manage Run-Time Environment"の画面から選択することはできるが、コンパイルしようとすると以下の様なエラーメッセージが出てしまう。

Error #603: 'Keil.MDK-Plus::USB:CORE:Release:6.13.0': component requires valid MDK-ARM Plus or MDK-ARM Professional license

そこで代わりにSTM32CubeMXが提供するUSBミドルウェアを使おうとしたところ、設定もコード生成もできるのに、ビルドには失敗することが分かった。

.\RTE\Device\STM32F072RBTx\STCubeGenerated\Inc\usb_device.h(33): error: #5: cannot open source input file "usbd_def.h": No such file or directory

原因: 必要なファイル・パスが自動で追加されないため

MDKのドキュメントに書かれているように、MDKが提供するソフトウァアパッケージ(CMSIS-Driver)はSTM32CubeMXが生成するHAL(Hardware Abstraction Layer)を利用するため、STM32CubeMXが生成したHALは自動的にuVisionプロジェクトに追加される。一方で、MDKが関知しないSTM32CubeMXのミドルウェアはuVisionプロジェクトに追加されないことが分かった。

例えばUSBデバイスのミドルウェアの場合、STCubeGenerated以下に生成されるUSB関連のミドルウェアやユーザカスタムのコードやインクルードパスが必要だが、元のuVisionプロジェクトに追加されない。そのために、"usbd_def.h"が無いというエラーにつながった。

対策: 手動でファイル・パスを追加する

STM32CubeMXが生成したuVisionプロジェクトSTCubeGenerated.uvprojxには、以下のように元のuVisionプロジェクトにないUSBミドルウェア関連のファイルusbd_*.cが含まれている。

これを参考に、元のuVisionプロジェクトに以下の8ファイルを追加する。

  • プロジェクトルート\RTE\Device\STM32F072RBTx\STCubeGenerated\Middlewares\ST\STM32_USB_Device_Library\Class\Core\Src
    • usbd_core.c
    • usbd_ctlreq.c
    • usbd_ioreq.c
  • プロジェクトルート\RTE\Device\STM32F072RBTx\STCubeGenerated\Middlewares\ST\STM32_USB_Device_Library\Class\CDC\Src
    • usbd_cdc.c
  • プロジェクトルート\RTE\Device\STM32F072RBTx\STCubeGenerated\Src
    • usb_device.c
    • usbd_conf.c
    • usbd_desc.c
    • usbd_cdc_if.c

更にusbd_*.cから参照されるヘッダを探索できるよう、USBミドルウェアのヘッダが格納されたパスをインクルードパスに追加する。

  • プロジェクトルート\RTE\Device\STM32F072RBTx\STCubeGenerated\Middlewares\ST\STM32_USB_Device_Library\Class\Core\Inc
  • プロジェクトルート\RTE\Device\STM32F072RBTx\STCubeGenerated\Middlewares\ST\STM32_USB_Device_Library\Class\CDC\Inc
  • プロジェクトルート\RTE\Device\STM32F072RBTx\STCubeGenerated\Inc

これらの設定をすることで、元のuVisionプロジェクトもビルドできるようになる。

注意

STM32CubeMXのUSBミドルウェアを使用する場合、以下に示すCMSIS-DriverのUSB Device(API)を追加してはならない。

追加すると、CMSIS-DriverとSTM32CubeMXで同名の関数(HAL関連)を定義してるためにリンカエラーが発生する。

linking...
.\Objects\mdk.axf: Error: L6200E: Symbol HAL_PCD_ConnectCallback multiply defined (by usbd_stm32f0xx.o and usbd_conf.o).
.\Objects\mdk.axf: Error: L6200E: Symbol HAL_PCD_DataInStageCallback multiply defined (by usbd_stm32f0xx.o and usbd_conf.o).
.\Objects\mdk.axf: Error: L6200E: Symbol HAL_PCD_DataOutStageCallback multiply defined (by usbd_stm32f0xx.o and usbd_conf.o).
.\Objects\mdk.axf: Error: L6200E: Symbol HAL_PCD_DisconnectCallback multiply defined (by usbd_stm32f0xx.o and usbd_conf.o).
.\Objects\mdk.axf: Error: L6200E: Symbol HAL_PCD_ISOINIncompleteCallback multiply defined (by usbd_stm32f0xx.o and usbd_conf.o).
.\Objects\mdk.axf: Error: L6200E: Symbol HAL_PCD_ISOOUTIncompleteCallback multiply defined (by usbd_stm32f0xx.o and usbd_conf.o).
.\Objects\mdk.axf: Error: L6200E: Symbol HAL_PCD_ResetCallback multiply defined (by usbd_stm32f0xx.o and usbd_conf.o).
.\Objects\mdk.axf: Error: L6200E: Symbol HAL_PCD_ResumeCallback multiply defined (by usbd_stm32f0xx.o and usbd_conf.o).
.\Objects\mdk.axf: Error: L6200E: Symbol HAL_PCD_SetupStageCallback multiply defined (by usbd_stm32f0xx.o and usbd_conf.o).
.\Objects\mdk.axf: Error: L6200E: Symbol HAL_PCD_SuspendCallback multiply defined (by usbd_stm32f0xx.o and usbd_conf.o).
Not enough information to list image symbols.
Not enough information to list load addresses in the image map.
Finished: 2 information, 0 warning and 10 error messages.
".\Objects\mdk.axf" - 10 Error(s), 18 Warning(s).

まとめ

Keil社のMDKは、ソフトウェアパッケージに必要なHAL・main・startupなどをSTM32CubeMXで生成したら、uVisionプロジェクトに追加してくれる。一方で、MDKと無関係にSTM32CubeMXで生成したコード(USBデバイスのミドルウェアなど)には関知しないので、手動でuVisionプロジェクトに追加する必要がある。

参考: MDKのドキュメント

MDKの"Manage Run-Time Environment"からDeviceを選択し、STM32Cube Frameworkの説明へのリンクを開くと、MDKとSTM23CubeMXの関係について説明を読むことができる。