usb_serial_rtic.rs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. //! CDC-ACM serial port example using cortex-m-rtic.
  2. //! Target board: Blue Pill
  3. #![no_main]
  4. #![no_std]
  5. #![allow(non_snake_case)]
  6. extern crate panic_semihosting;
  7. use cortex_m::asm::delay;
  8. use embedded_hal::digital::v2::OutputPin;
  9. use rtic::app;
  10. use stm32f1xx_hal::prelude::*;
  11. use stm32f1xx_hal::usb::{Peripheral, UsbBus, UsbBusType};
  12. use usb_device::bus;
  13. use usb_device::prelude::*;
  14. use usbd_serial::{SerialPort, USB_CLASS_CDC};
  15. #[app(device = stm32f1xx_hal::stm32, peripherals = true)]
  16. const APP: () = {
  17. struct Resources {
  18. usb_dev: UsbDevice<'static, UsbBusType>,
  19. serial: SerialPort<'static, UsbBusType>,
  20. }
  21. #[init]
  22. fn init(cx: init::Context) -> init::LateResources {
  23. static mut USB_BUS: Option<bus::UsbBusAllocator<UsbBusType>> = None;
  24. let mut flash = cx.device.FLASH.constrain();
  25. let mut rcc = cx.device.RCC.constrain();
  26. let clocks = rcc
  27. .cfgr
  28. .use_hse(8.mhz())
  29. .sysclk(48.mhz())
  30. .pclk1(24.mhz())
  31. .freeze(&mut flash.acr);
  32. assert!(clocks.usbclk_valid());
  33. let mut gpioa = cx.device.GPIOA.split(&mut rcc.apb2);
  34. // BluePill board has a pull-up resistor on the D+ line.
  35. // Pull the D+ pin down to send a RESET condition to the USB bus.
  36. // This forced reset is needed only for development, without it host
  37. // will not reset your device when you upload new firmware.
  38. let mut usb_dp = gpioa.pa12.into_push_pull_output(&mut gpioa.crh);
  39. usb_dp.set_low().unwrap();
  40. delay(clocks.sysclk().0 / 100);
  41. let usb_dm = gpioa.pa11;
  42. let usb_dp = usb_dp.into_floating_input(&mut gpioa.crh);
  43. let usb = Peripheral {
  44. usb: cx.device.USB,
  45. pin_dm: usb_dm,
  46. pin_dp: usb_dp,
  47. };
  48. *USB_BUS = Some(UsbBus::new(usb));
  49. let serial = SerialPort::new(USB_BUS.as_ref().unwrap());
  50. let usb_dev = UsbDeviceBuilder::new(USB_BUS.as_ref().unwrap(), UsbVidPid(0x16c0, 0x27dd))
  51. .manufacturer("Fake company")
  52. .product("Serial port")
  53. .serial_number("TEST")
  54. .device_class(USB_CLASS_CDC)
  55. .build();
  56. init::LateResources { usb_dev, serial }
  57. }
  58. #[task(binds = USB_HP_CAN_TX, resources = [usb_dev, serial])]
  59. fn usb_tx(mut cx: usb_tx::Context) {
  60. usb_poll(&mut cx.resources.usb_dev, &mut cx.resources.serial);
  61. }
  62. #[task(binds = USB_LP_CAN_RX0, resources = [usb_dev, serial])]
  63. fn usb_rx0(mut cx: usb_rx0::Context) {
  64. usb_poll(&mut cx.resources.usb_dev, &mut cx.resources.serial);
  65. }
  66. };
  67. fn usb_poll<B: bus::UsbBus>(
  68. usb_dev: &mut UsbDevice<'static, B>,
  69. serial: &mut SerialPort<'static, B>,
  70. ) {
  71. if !usb_dev.poll(&mut [serial]) {
  72. return;
  73. }
  74. let mut buf = [0u8; 8];
  75. match serial.read(&mut buf) {
  76. Ok(count) if count > 0 => {
  77. // Echo back in upper case
  78. for c in buf[0..count].iter_mut() {
  79. if 0x61 <= *c && *c <= 0x7a {
  80. *c &= !0x20;
  81. }
  82. }
  83. serial.write(&buf[0..count]).ok();
  84. }
  85. _ => {}
  86. }
  87. }