usb_serial.rs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. //! CDC-ACM serial port example using polling in a busy loop.
  2. //! Target board: Blue Pill
  3. //!
  4. //! Note:
  5. //! When building this since this is a larger program,
  6. //! one would need to build it using release profile
  7. //! since debug profiles generates artifacts that
  8. //! cause FLASH overflow errors due to their size
  9. #![no_std]
  10. #![no_main]
  11. extern crate panic_semihosting;
  12. use cortex_m::asm::delay;
  13. use cortex_m_rt::entry;
  14. use embedded_hal::digital::v2::OutputPin;
  15. use stm32f1xx_hal::usb::{Peripheral, UsbBus};
  16. use stm32f1xx_hal::{prelude::*, stm32};
  17. use usb_device::prelude::*;
  18. use usbd_serial::{SerialPort, USB_CLASS_CDC};
  19. #[entry]
  20. fn main() -> ! {
  21. let dp = pac::Peripherals::take().unwrap();
  22. let mut flash = dp.FLASH.constrain();
  23. let mut rcc = dp.RCC.constrain();
  24. let clocks = rcc
  25. .cfgr
  26. .use_hse(8.mhz())
  27. .sysclk(48.mhz())
  28. .pclk1(24.mhz())
  29. .freeze(&mut flash.acr);
  30. assert!(clocks.usbclk_valid());
  31. // Configure the on-board LED (PC13, green)
  32. let mut gpioc = dp.GPIOC.split(&mut rcc.apb2);
  33. let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
  34. led.set_high(); // Turn off
  35. let mut gpioa = dp.GPIOA.split(&mut rcc.apb2);
  36. // BluePill board has a pull-up resistor on the D+ line.
  37. // Pull the D+ pin down to send a RESET condition to the USB bus.
  38. // This forced reset is needed only for development, without it host
  39. // will not reset your device when you upload new firmware.
  40. let mut usb_dp = gpioa.pa12.into_push_pull_output(&mut gpioa.crh);
  41. usb_dp.set_low();
  42. delay(clocks.sysclk().0 / 100);
  43. let usb = Peripheral {
  44. usb: dp.USB,
  45. pin_dm: gpioa.pa11,
  46. pin_dp: usb_dp.into_floating_input(&mut gpioa.crh),
  47. };
  48. let usb_bus = UsbBus::new(usb);
  49. let mut serial = SerialPort::new(&usb_bus);
  50. let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd))
  51. .manufacturer("Fake company")
  52. .product("Serial port")
  53. .serial_number("TEST")
  54. .device_class(USB_CLASS_CDC)
  55. .build();
  56. loop {
  57. if !usb_dev.poll(&mut [&mut serial]) {
  58. continue;
  59. }
  60. let mut buf = [0u8; 64];
  61. match serial.read(&mut buf) {
  62. Ok(count) if count > 0 => {
  63. led.set_low(); // Turn on
  64. // Echo back in upper case
  65. for c in buf[0..count].iter_mut() {
  66. if 0x61 <= *c && *c <= 0x7a {
  67. *c &= !0x20;
  68. }
  69. }
  70. let mut write_offset = 0;
  71. while write_offset < count {
  72. match serial.write(&buf[write_offset..count]) {
  73. Ok(len) if len > 0 => {
  74. write_offset += len;
  75. }
  76. _ => {}
  77. }
  78. }
  79. }
  80. _ => {}
  81. }
  82. led.set_high(); // Turn off
  83. }
  84. }