先週の続き...の前に、先々週の話を忘れていたのでまずはこちらから。usbd_conf.hが2種類あるという話であるが、実はこれはSTM32F407VGのサンプルコードに含まれている(STM32F4-Discoveryのサンプルコードではない)。こちらのページのDesign supportタブの下のほうにFirmwareが並んでいるが、ここにある"STM32F105/7, STM32F2 and STM32F4 USB on-the-go Host and device library"を展開して出てくるSTM32_USB-Host-Device_Lib_V2.1.0\Project\USB_Device_Examples\VCP\inc の下にあるusbd_conf.hが元ネタである。もっともこちらのファイルは、原稿執筆時点でのバージョンはVersion 1.1.0(2012年3月19日版)であるが、これ以前にSTMicroがリリースしていたVersion 1.0.0版(2011年7月19日版)というのがあちこちのWeb上(たとえばここ)で散見されており、とりあえずはこちらの記述を拝借したという次第。usbd_conf.hに関してVersion 1.0.0とVersion 1.1.0の違いを見ると、USB_MAX_STR_DESC_SIZの値が50か255かの違いだけなので、後でVersion 1.1.0に差し替えるとしても当面は問題なさそうである。
さて、先週の続き。USBD_Init()の最後のUSR_cbだが、こちらはusbd_usr.cの中で定義されており、
USBD_Usr_cb_TypeDef USR_cb =
{
USBD_USR_Init,
USBD_USR_DeviceReset,
USBD_USR_DeviceConfigured,
USBD_USR_DeviceSuspended,
USBD_USR_DeviceResumed,
};
とされている。これらの関数はやはりusbd_usr.cの中で定義されており、たとえばUSBD_USR_Init()であれば、
void USBD_USR_Init(void)
{
/* Initialize LEDs */
STM_EVAL_LEDInit(LED1);
STM_EVAL_LEDInit(LED2);
STM_EVAL_LEDInit(LED3);
STM_EVAL_LEDInit(LED4);
/* Initialize the LCD */
#ifdef USE_STM3210C_EVAL
STM3210C_LCD_Init();
#else
STM322xG_LCD_Init();
#endif
LCD_LOG_Init();
#ifdef USE_USB_OTG_HS
LCD_LOG_SetHeader(" USB OTG HS VCP Device");
#else
LCD_LOG_SetHeader(" USB OTG FS VCP Device");
#endif
LCD_UsrLog("> USB device library started.\n");
LCD_LOG_SetFooter (" USB Device Library v1.0.0" );
}
てな具合になっている。ボードのLCDの初期かはこちらでまとめて行われているようだ。ちょっとUSB Driverの中身を確認ということでusbd_core.cの中に含まれているUSBD_IInit()の中を見てみると、
/**
* @brief USBD_Init
* Initailizes the device stack and load the class driver
* @param pdev: device instance
* @param core_address: USB OTG core ID
* @param class_cb: Class callback structure address
* @param usr_cb: User callback structure address
* @retval None
*/
void USBD_Init(USB_OTG_CORE_HANDLE *pdev,
USB_OTG_CORE_ID_TypeDef coreID,
USBD_DEVICE *pDevice,
USBD_Class_cb_TypeDef *class_cb,
USBD_Usr_cb_TypeDef *usr_cb)
{
/* Hardware Init */
USB_OTG_BSP_Init(pdev);
USBD_DeInit(pdev);
/*Register class and user callbacks */
pdev->dev.class_cb = class_cb;
pdev->dev.usr_cb = usr_cb;
pdev->dev.usr_device = pDevice;
/* set USB OTG core params */
DCD_Init(pdev , coreID);
/* Upon Init call usr callback */
pdev->dev.usr_cb->Init();
/* Enable Interrupts */
USB_OTG_BSP_EnableInterrupt(pdev);
}
といった具合になっている。USR_cbで積んだ中身は、USBD_Initの最後の引数で渡されてくる形であるが、まずUSB_OTG_BSP_Init()でボードの初期化、USBD_DeInit()でドライバの初期化の後、pdev->dev.usr_cb = usr_cbという形でデバイスドライバを管理する構造体にUSR_cbを登録し、ついでpdev->dev.usr_cb->Init();としてUSBD_USR_Init()を呼び出している。これは他の関数も同じで、Init/DeviceReset/DeviceConfigured/DeviceSuspended/DeviceResumedの5つの状態については、usbd_usr.cの中の記述を書き換えれば良いことが判った。
ただこれだと、肝心の送受信の際のCallbackが皆無である。こちらはusbd_cdc_vcp.cの中に含まれている。
(続く)