- 主题:GD32的库真是写的稀烂
没,STM32的我就用过103的USB。
最近在用GD32的USB,它硬件上有两个IP,USBD和USBFS,USBD兼容STM32,USBFS完全是另外一个样子,寄存器地址配置完全不同。
USB用来很简单,但是开发真挺麻烦,很少有人从0开始写代码,各个MCU都有自己的USB库。
感觉应该是这些MCU上最麻烦的一个外设了。
AVR上那个软件模拟USBLS的库还挺神奇的,ARM上好像没人这么干。
【 在 tom6bj (tom) 的大作中提到: 】
: 对了, f4的usb你玩了没? f1和f3似乎能通用, f0也差不多, 但是到f4完全变样了
--
FROM 36.45.172.*
贴个usb的例子,如果用寄存器要写死人吧?
//! CDC-ACM serial port example using interrupts.
//! Target board: Blue Pill
#![no_std]
#![no_main]
extern crate panic_semihosting;
use cortex_m::asm::{delay, wfi};
use cortex_m_rt::entry;
use embedded_hal::digital::v2::OutputPin;
use stm32f1xx_hal::pac::{interrupt, Interrupt};
use stm32f1xx_hal::usb::{Peripheral, UsbBus, UsbBusType};
use stm32f1xx_hal::{prelude::*, stm32};
use usb_device::{bus::UsbBusAllocator, prelude::*};
use usbd_serial::{SerialPort, USB_CLASS_CDC};
static mut USB_BUS: Option<UsbBusAllocator<UsbBusType>> = None;
static mut USB_SERIAL: Option<usbd_serial::SerialPort<UsbBusType>> = None;
static mut USB_DEVICE: Option<UsbDevice<UsbBusType>> = None;
#[entry]
fn main() -> ! {
let p = cortex_m::Peripherals::take().unwrap();
let dp = pac::Peripherals::take().unwrap();
let mut flash = dp.FLASH.constrain();
let mut rcc = dp.RCC.constrain();
let clocks = rcc
.cfgr
.use_hse(8.mhz())
.sysclk(48.mhz())
.pclk1(24.mhz())
.freeze(&mut flash.acr);
assert!(clocks.usbclk_valid());
let mut gpioa = dp.GPIOA.split(&mut rcc.apb2);
// BluePill board has a pull-up resistor on the D+ line.
// Pull the D+ pin down to send a RESET condition to the USB bus.
// This forced reset is needed only for development, without it host
// will not reset your device when you upload new firmware.
let mut usb_dp = gpioa.pa12.into_push_pull_output(&mut gpioa.crh);
usb_dp.set_low();
delay(clocks.sysclk().0 / 100);
let usb_dm = gpioa.pa11;
let usb_dp = usb_dp.into_floating_input(&mut gpioa.crh);
let usb = Peripheral {
usb: dp.USB,
pin_dm: usb_dm,
pin_dp: usb_dp,
};
// Unsafe to allow access to static variables
unsafe {
let bus = UsbBus::new(usb);
USB_BUS = Some(bus);
USB_SERIAL = Some(SerialPort::new(USB_BUS.as_ref().unwrap()));
let usb_dev = UsbDeviceBuilder::new(USB_BUS.as_ref().unwrap(), UsbVidPid(0x16c0, 0x27dd))
.manufacturer("Fake company")
.product("Serial port")
.serial_number("TEST")
.device_class(USB_CLASS_CDC)
.build();
USB_DEVICE = Some(usb_dev);
}
let mut nvic = p.NVIC;
nvic.enable(Interrupt::USB_HP_CAN_TX);
nvic.enable(Interrupt::USB_LP_CAN_RX0);
loop {
wfi();
}
}
#[interrupt]
fn USB_HP_CAN_TX() {
usb_interrupt();
}
#[interrupt]
fn USB_LP_CAN_RX0() {
usb_interrupt();
}
fn usb_interrupt() {
let usb_dev = unsafe { USB_DEVICE.as_mut().unwrap() };
let serial = unsafe { USB_SERIAL.as_mut().unwrap() };
if !usb_dev.poll(&mut [serial]) {
return;
}
let mut buf = [0u8; 8];
match serial.read(&mut buf) {
Ok(count) if count > 0 => {
// Echo back in upper case
for c in buf[0..count].iter_mut() {
if 0x61 <= *c && *c <= 0x7a {
*c &= !0x20;
}
}
serial.write(&buf[0..count]).ok();
}
_ => {}
}
}
【 在 dismoon (伐开心要包包) 的大作中提到: 】
: 所以为啥你非要用HAL,寄存器操作不香么
--
FROM 180.109.234.*
gd32的库用了大量的宏,很多操作在预编译阶段就搞定了,可读性略差,感觉效率应该高一点。对于倾向于直接使用寄存器操作的用户更友好。
寄存器描述,STM32用结构体,GD32用宏;前者可读性好一点,后者移植性好一点。
【 在 tom6bj (tom) 的大作中提到: 】
: 具体怎么烂法, 举个例子?
: 我是觉得取寄存器时用函数调用风格的RDATA(USART1)之类不如stm32官方库的USART1->RDR看着舒服, 不过纯小写+下划线的命名风格比匈牙利式看起来更顺眼.
: 个人喜好问题吧
: ...................
--
FROM 36.45.172.*
编译慢可以等等,生成的二进制文件尺寸和C比如何?我比较关心这个。
HAL库太臃肿了,只要用了,目标文件就小不了。
【 在 lvsoft (Lv(The Last Guardian)) 的大作中提到: 】
: 更要命的是这样的库还有peripheral,hal,ll三套...基本上是重新定义了“烂的最
: 高境界”...
: 在rust下不需要折腾makefile,折腾各种库的编译环境,各种库都是模块化的直接
: ...................
--
FROM 36.45.172.*
v-usb?
主要是avr能做到指令级别的运行时间可控吧,用汇编指令凑出usb时序
stm32够呛吧...
以前在哪看到有人考虑给stm8弄一个,出了半成品吧
不过stm8那点资源跑了usb也剩不下多少了
【 在 spadger (imdx) 的大作中提到: 】
没,STM32的我就用过103的USB。
最近在用GD32的USB,它硬件上有两个IP,USBD和USBFS,USBD兼容STM32,USBFS完全是另外一个样子,寄存器地址配置完全不同。
USB用来很简单,但是开发真挺麻烦,很少有人从0开始写代码,各个MCU都有自己的USB库。
感觉应该是这些MCU上最麻烦的一个外设了。
AVR上那个软件模拟USBLS的库还挺神奇的,ARM上好像没人这么干。
【 在 tom6bj (tom) 的大作中提到: 】
: 对了, f4的usb你玩了没? f1和f3似乎能通用, f0也差不多, 但是到f4完全变样了
--
FROM 106.121.158.*
LL库还好,基本是把寄存器zero-cost地翻译成人类语言了
rust还没进化完成是个问题,跟早几年的go一样,演化速度快 学习跟不上趟...我在等它啥时候release 1.0
不过我觉得未来会有在rust基础上演化出来的更合乎人类思维的语言,解决跟编译器斗智斗勇的问题。。。
【 在 lvsoft 的大作中提到: 】
: 更要命的是这样的库还有peripheral,hal,ll三套...基本上是重新定义了“烂的最
: 高境界”...
: 在rust下不需要折腾makefile,折腾各种库的编译环境,各种库都是模块化的直接
: ...................
--
FROM 111.198.57.*
这是底层轮子都有了吧。。。
我数了一下, stm32f10x官方usb库, 回调函数最多得42个
(实际用不了这么多, 很多是nop_process)
【 在 lvsoft (Lv(The Last Guardian)) 的大作中提到: 】
: 贴个usb的例子,如果用寄存器要写死人吧?
: //! CDC-ACM serial port example using interrupts.
: //! Target board: Blue Pill
: ...................
--
FROM 106.121.158.*
结构体风格的移植性有什么问题呢, 都是标准c
stm32官方库通过了什么ansi认证的吧
【 在 spadger (imdx) 的大作中提到: 】
gd32的库用了大量的宏,很多操作在预编译阶段就搞定了,可读性略差,感觉效率应该高一点。对于倾向于直接使用寄存器操作的用户更友好。
寄存器描述,STM32用结构体,GD32用宏;前者可读性好一点,后者移植性好一点。
【 在 tom6bj (tom) 的大作中提到: 】
: 具体怎么烂法, 举个例子?
: 我是觉得取寄存器时用函数调用风格的RDATA(USART1)之类不如stm32官方库的USART1->RDR看着舒服, 不过纯小写+下划线的命名风格比匈牙利式看起来更顺眼.
: 个人喜好问题吧
: ...................
--
FROM 106.121.158.*
我不用hal啊。。。我用ll...
第一次用hal写个串口收发简直像是被喂了shit...
【 在 dismoon 的大作中提到: 】
: 所以为啥你非要用HAL,寄存器操作不香么
:
--
FROM 111.198.57.*
感觉hal是给没写过mcu, 从java/web之类转行过来的码农准备的吧。。。
【 在 eggcar (eggcar) 的大作中提到: 】
: 我不用hal啊。。。我用ll...
: 第一次用hal写个串口收发简直像是被喂了shit...
--
FROM 106.121.158.*