123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- //! CDC-ACM serial port example using cortex-m-rtfm.
- //! Target board: Blue Pill
- #![no_main]
- #![no_std]
- #![allow(non_snake_case)]
- extern crate panic_semihosting;
- use cortex_m::asm::delay;
- use embedded_hal::digital::v2::OutputPin;
- use rtfm::app;
- use stm32f1xx_hal::prelude::*;
- use stm32f1xx_hal::usb::{Peripheral, UsbBus, UsbBusType};
- use usb_device::bus;
- use usb_device::prelude::*;
- use usbd_serial::{SerialPort, USB_CLASS_CDC};
- #[app(device = stm32f1xx_hal::stm32, peripherals = true)]
- const APP: () = {
- struct Resources {
- usb_dev: UsbDevice<'static, UsbBusType>,
- serial: SerialPort<'static, UsbBusType>,
- }
- #[init]
- fn init(cx: init::Context) -> init::LateResources {
- static mut USB_BUS: Option<bus::UsbBusAllocator<UsbBusType>> = None;
- let mut flash = cx.device.FLASH.constrain();
- let mut rcc = cx.device.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 = cx.device.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().unwrap();
- 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: cx.device.USB,
- pin_dm: usb_dm,
- pin_dp: usb_dp,
- };
- *USB_BUS = Some(UsbBus::new(usb));
- let serial = 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();
- init::LateResources { usb_dev, serial }
- }
- #[task(binds = USB_HP_CAN_TX, resources = [usb_dev, serial])]
- fn usb_tx(mut cx: usb_tx::Context) {
- usb_poll(&mut cx.resources.usb_dev, &mut cx.resources.serial);
- }
- #[task(binds = USB_LP_CAN_RX0, resources = [usb_dev, serial])]
- fn usb_rx0(mut cx: usb_rx0::Context) {
- usb_poll(&mut cx.resources.usb_dev, &mut cx.resources.serial);
- }
- };
- fn usb_poll<B: bus::UsbBus>(
- usb_dev: &mut UsbDevice<'static, B>,
- serial: &mut SerialPort<'static, B>,
- ) {
- 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();
- }
- _ => {}
- }
- }
|