現(xiàn)狀
- 基于STM32CubeMX的F103/F40X的USB堆棧測試完畢氨淌;
- 基于Mbed OS的F103/F40X的USB堆棧測試完畢必峰;
- 主要測試USB CDC設(shè)備;
- 基于USB ACM/CDC實(shí)現(xiàn)nRF24L01及類似“小無線”系統(tǒng)集成;
- 基于USB ACM/CDC開發(fā)了VT100 cmdline
- 基于USB ACM/CDC和cmdline實(shí)現(xiàn)SPI NOR Flash的讀寫洁段;
- 基于USB ACM/CDC開發(fā)HCI定制協(xié)議;
- 基于Linux udev的USB設(shè)備插入拔出時(shí)間的檢測质欲;
計(jì)劃
- 開發(fā)其他TLV類型二進(jìn)制協(xié)議和基于字符串的JSON RPC等協(xié)議树埠;
- 實(shí)現(xiàn)xmodem傳輸;
- 實(shí)現(xiàn)I2C設(shè)備掃描與訪問把敞;
- 更新現(xiàn)有的LoRaPHY/Aloha/LoRaWAN USB Dongle弥奸;
- 支持C8T6/RCT6等多種核心板,以應(yīng)對更加復(fù)雜的堆棧奋早;
- 支持USB ECM盛霎,以直接支持6LowPAN等物聯(lián)網(wǎng)設(shè)備;
- 集成Arduino STM32的Bootloader實(shí)現(xiàn)固件升級耽装。
開源設(shè)計(jì)與板級產(chǎn)品
- 大部分設(shè)計(jì)都是開源設(shè)計(jì)愤炸;
- 或有根據(jù)客戶要求定制進(jìn)行設(shè)計(jì);
代碼設(shè)計(jì)過程
以下內(nèi)容針對Mbed C++和STM32F103/F407
今天完成的主要是在USB通道上實(shí)現(xiàn)VT100 cmdline掉奄,可以通過TeraTerm終端來配置管理設(shè)備规个,或者通過專門的cmd/GUI上位機(jī)程序?qū)崿F(xiàn)自動化配置。最早基于C和串口姓建,在Mbed Serial類上移植也很容易诞仓。但是在USB信道上實(shí)現(xiàn)cmdline很花費(fèi)了一些時(shí)間,且有了反復(fù)速兔。主要原因是USB對象初始化的特殊性墅拭,以及Mbed C++與基于標(biāo)準(zhǔn)庫或HAL庫的原始設(shè)計(jì)的差異所造成的。
基于標(biāo)準(zhǔn)庫或者HAL庫的模板一般是:
- 將所需硬件資源(串口涣狗、GPIO)聲明為main的全局變量
- 將USB聲明為 extern 全局變量
- 在主函數(shù)中配置時(shí)鐘谍婉,初始化這些硬件資源
- 展開應(yīng)用邏輯
發(fā)現(xiàn)STM32 CubeMX的USB實(shí)例是usb_device.c中的全局變量。 這和一般的硬件資源如GPIO/ADC/PWM/CAN/UART都有所不同镀钓。
// Private in main.c
CAN_HandleTypeDef hcan;
RTC_HandleTypeDef hrtc;
UART_HandleTypeDef huart1;
int main(void){
HAL_Init();
SystemClock_Config(); // RCC init before any other resources
MX_GPIO_Init();
MX_CAN_Init();
MX_USART1_UART_Init();
MX_RTC_Init();
MX_USB_DEVICE_Init(); // USB init here
while(1){
...
}
}
main.c
USBD_HandleTypeDef hUsbDeviceFS;
void MX_USB_DEVICE_Init(void)
{
USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);
USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC);
USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS);
USBD_Start(&hUsbDeviceFS);
}
usb_device.c
extern USBD_HandleTypeDef hUsbDeviceFS;
usb_device.h
而基于Mbed C++有些特殊穗熬。
DigitalOut myled(DBG_LED); // See main.h for hardware issue
cmdline cmdhandler;
// You can put USBSerial/USBTerminal here, but will not be enumerated in F103
//USBSerial usbSerial(0x1f00, 0x2012, 0x0001, false);
USBTerminal *term;
int main(){
confSysClock(); // RCC init first
Serial uart(PA_9, PA_10, 115200);
//USBSerial usbSerial(0x1f00, 0x2012, 0x0001, false);
USBTerminal usbSerial(0x1f00, 0x2012, 0x0001, false);
term = &usbSerial;
}
main.cpp
USB對于時(shí)鐘是非常敏感的,所以必須在系統(tǒng)時(shí)鐘配置正確后才能夠產(chǎn)生USB對象丁溅。
在Mbed C++中祖搓,在調(diào)用main函數(shù)之前餐弱,進(jìn)行時(shí)鐘配置和對象實(shí)例化盛险。RCC時(shí)鐘配置隱藏在Mbed Library中缨该,如果對象在Main函數(shù)之外,視為公有對象饰序,也在main函數(shù)之前進(jìn)行實(shí)例化领虹。
如果將USB對象作為公有對象,F(xiàn)407工作正常求豫,而F103工作不正常塌衰,表現(xiàn)在枚舉失敗诉稍。換而言之,在F407代碼中最疆,可以將USBSerial/USBTerminal在main函數(shù)之外聲明杯巨,且工作正常。但是F103代碼中努酸,同樣的代碼服爷,編譯通過,但是枚舉失敗获诈。
所以第三方開發(fā)者打了一個(gè)補(bǔ)丁仍源,在main函數(shù)中增加了一個(gè)confSysClock()。有興趣的話舔涎,可以查看RCC寄存器的數(shù)值笼踩。
由于時(shí)鐘是main函數(shù)中調(diào)用的,間接造成USB對象(USBSerial及其子類USBTerminal)是main函數(shù)中的對象亡嫌,其他模塊和函數(shù)無法訪問嚎于。
解決方法是在main.cpp中預(yù)留一個(gè)USB對象指針,讓其他函數(shù)和其他模塊可以訪問到USB對象挟冠。代價(jià)是USB對象的所有方法必須采用“->”來訪問于购。這也就導(dǎo)致了基于Serial對象和USB對象的代碼存在兩套,這實(shí)在違背了OOP的原則知染。
由此看來肋僧,基于Serial對象,基于F103的USBSerial持舆,基于F407的USBSerial的通道色瘩,居然出現(xiàn)了兩套(確切地說是2.5套)代碼伪窖。這種情況可能同樣會影響到其他協(xié)議逸寓,包括HCI/SIP/TLV/JSON等。
對于ARM來說覆山,USB不是IoT的一部分竹伸。他們的IoT/Connectivity主要包括的是Cellular Modem/WiFi/BLE/LoRaWAN/BLE/TLS/MQTT等。
要合并代碼簇宽,還需要開發(fā)者自己動手勋篓。要么統(tǒng)一為指針類型;要么期待Mbed底層得到修改魏割。然而這些代碼都是基于Mbed 2譬嚣,而Mbed 5并沒有對USB堆棧進(jìn)行維護(hù)。需要開發(fā)者自己Backport钞它。代碼在此:ARM Mbed OS STM32F103的系統(tǒng)時(shí)鐘配置代碼