├── .cargo ├── config.toml ├── config_defmt.toml ├── config_embed.toml ├── config_runner_gdb.toml └── config_runner_qeum.toml ├── .env ├── .gdbinit ├── .gitattributes ├── .gitignore ├── .vscode └── settings.json ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── app ├── adc │ ├── ad_multichannel │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ └── ad_single_channel │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ └── main.rs ├── basic │ ├── flash_tool_defmt │ │ ├── .cargo │ │ │ └── config.toml │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── build.rs │ │ ├── memory.x │ │ └── src │ │ │ └── main.rs │ ├── flash_tool_embed │ │ ├── .cargo │ │ │ └── config.toml │ │ ├── Cargo.toml │ │ ├── Embed.toml │ │ ├── README.md │ │ ├── build.rs │ │ ├── memory.x │ │ └── src │ │ │ └── main.rs │ ├── helloworld │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── panics │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ └── unit_testsuite │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ └── lib.rs ├── delay │ ├── asm_delay │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── syst_delay │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── syst_timer_delay │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ └── tim2_delay │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ └── main.rs ├── dma │ ├── dma_data_continuous_transfer │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── dma_data_transfer │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── print_memory_address │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── scan_dma_and_ad_multichannel │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── scan_dma_and_ad_multichannel_loop │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ └── scan_dma_and_ad_multichannel_peek │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ └── main.rs ├── flash │ ├── internal_flash │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ └── read_chip_id │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ └── main.rs ├── free_rtos │ └── free_rtos_blinky │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── build.rs │ │ └── src │ │ ├── FreeRTOSConfig.h │ │ └── main.rs ├── general_gpio │ ├── blinky │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── buzzer │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── delay_blinky │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── dynamic_gpio │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── ffi-blinky │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── key_control_led │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── led_flow_light │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── light_sensor_control_buzzer │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── multi_mode_gpio │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── tim2_timer_delay_blinky │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── timer_blinky │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ └── turns_user_led │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ └── main.rs ├── i2c │ ├── i2c_hard_mpu6050 │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── i2c_mpu6050_crate │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── i2c_oled_show_character │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ └── i2c_soft_mpu6050 │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ └── main.rs ├── interrupt │ ├── key_control_led_exti │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── opposing_infrared_sensor_count │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── opposing_infrared_sensor_count2 │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── rotary_encoder_count │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── rtc_alarm_blinky_irq │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── sys_timer_interrupt │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── timer_external_clock │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── timer_interrupt_count_by_hz │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ └── timer_interrupt_count_by_seces │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ └── main.rs ├── port_remap │ └── disable_jtag_ports │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ └── main.rs ├── pwm │ ├── pwm_custom │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── pwm_driven_motor │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── pwm_driven_servo │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── pwm_input_capture_freq_duty_cycle │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── pwm_led │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── pwm_led2 │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── pwm_led_remap │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── pwm_rotary_encoder_count │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── pwm_rotary_encoder_speed │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ └── pwm_rotary_encoder_timer_speed │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ └── main.rs ├── pwr │ ├── sleep_mode_serial_tx_and_rx │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── standby_mode_rtc_counter │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── stop_mode_infrared_sensor_count │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ └── syst_freq │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ └── main.rs ├── rtc │ ├── rtc_alarm_blinky │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── rtc_bkp │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── rtc_bkp_dyn_data │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── rtc_counter │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ └── rtc_time │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ └── main.rs ├── rtic │ ├── exti_rtic │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── spawn_task_rtic │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ └── timer_interrupt_rtic │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ └── main.rs ├── spi │ ├── spi_hard_w25q64 │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── spi_nrf24l01 │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── spi_soft_w25q64 │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ └── spi_w25q_crate │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ └── main.rs ├── usart │ ├── serial_config │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── serial_continuous_tx_and_rx │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── serial_fmt │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── serial_hex_packet │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── serial_interrupt_idle │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── serial_reconfigure │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ ├── serial_text_packet │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── main.rs │ └── serial_tx_and_rx │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ └── main.rs └── wdg │ ├── iwdg │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs │ └── wwdg │ ├── Cargo.toml │ ├── README.md │ └── src │ └── main.rs ├── bak ├── link.x ├── signal_simulation.py └── udev │ └── rules.d │ ├── 49-stlinkv1.rules │ ├── 49-stlinkv2-1.rules │ ├── 49-stlinkv2.rules │ └── 49-stlinkv3.rules ├── build.rs ├── core ├── bindgen_hello │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── build.rs │ ├── hello │ │ ├── bar.c │ │ ├── bar.h │ │ ├── bindings.rs │ │ ├── hello.c │ │ └── hello.h │ ├── src │ │ └── lib.rs │ └── tests │ │ └── hello_demo.rs ├── ffi_hello │ ├── Cargo.toml │ ├── README.md │ ├── build.rs │ ├── hello │ │ ├── bar.c │ │ ├── bar.h │ │ ├── hello.c │ │ └── hello.h │ └── src │ │ └── lib.rs ├── hardware │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── flash_store │ │ ├── flash_rw.rs │ │ ├── mod.rs │ │ └── store.rs │ │ ├── key.rs │ │ ├── lib.rs │ │ ├── mpu6050 │ │ ├── conf.rs │ │ ├── mod.rs │ │ ├── mpu6050_hal.rs │ │ └── mpu6050_reg.rs │ │ ├── oled │ │ ├── font.rs │ │ ├── mod.rs │ │ ├── simple.rs │ │ └── utils.rs │ │ ├── serial.rs │ │ ├── syst │ │ ├── delay.rs │ │ └── mod.rs │ │ └── w25q64 │ │ ├── conf.rs │ │ ├── mod.rs │ │ ├── w25q64_hal.rs │ │ └── w25q64_reg.rs └── stm32f10x_rs │ ├── Cargo.toml │ ├── README.md │ ├── build.rs │ ├── src │ ├── bindings.rs │ └── lib.rs │ └── stm32f10x │ ├── Conf │ ├── stm32f10x_conf.h │ ├── stm32f10x_it.c │ └── stm32f10x_it.h │ ├── Library │ ├── misc.c │ ├── misc.h │ ├── stm32f10x_adc.c │ ├── stm32f10x_adc.h │ ├── stm32f10x_bkp.c │ ├── stm32f10x_bkp.h │ ├── stm32f10x_can.c │ ├── stm32f10x_can.h │ ├── stm32f10x_cec.c │ ├── stm32f10x_cec.h │ ├── stm32f10x_crc.c │ ├── stm32f10x_crc.h │ ├── stm32f10x_dac.c │ ├── stm32f10x_dac.h │ ├── stm32f10x_dbgmcu.c │ ├── stm32f10x_dbgmcu.h │ ├── stm32f10x_dma.c │ ├── stm32f10x_dma.h │ ├── stm32f10x_exti.c │ ├── stm32f10x_exti.h │ ├── stm32f10x_flash.c │ ├── stm32f10x_flash.h │ ├── stm32f10x_fsmc.c │ ├── stm32f10x_fsmc.h │ ├── stm32f10x_gpio.c │ ├── stm32f10x_gpio.h │ ├── stm32f10x_i2c.c │ ├── stm32f10x_i2c.h │ ├── stm32f10x_iwdg.c │ ├── stm32f10x_iwdg.h │ ├── stm32f10x_pwr.c │ ├── stm32f10x_pwr.h │ ├── stm32f10x_rcc.c │ ├── stm32f10x_rcc.h │ ├── stm32f10x_rtc.c │ ├── stm32f10x_rtc.h │ ├── stm32f10x_sdio.c │ ├── stm32f10x_sdio.h │ ├── stm32f10x_spi.c │ ├── stm32f10x_spi.h │ ├── stm32f10x_tim.c │ ├── stm32f10x_tim.h │ ├── stm32f10x_usart.c │ ├── stm32f10x_usart.h │ ├── stm32f10x_wwdg.c │ └── stm32f10x_wwdg.h │ ├── Start │ ├── core_cm3.c │ ├── core_cm3.h │ ├── startup_stm32f10x_cl.s │ ├── startup_stm32f10x_hd.s │ ├── startup_stm32f10x_hd_vl.s │ ├── startup_stm32f10x_ld.s │ ├── startup_stm32f10x_ld_vl.s │ ├── startup_stm32f10x_md.s │ ├── startup_stm32f10x_md_vl.s │ ├── startup_stm32f10x_xl.s │ ├── stm32f10x.h │ ├── system_stm32f10x.c │ └── system_stm32f10x.h │ └── System │ ├── delay.c │ └── delay.h ├── docs ├── AI协助.md ├── Archlinux环境搭建.md ├── BluePillPinout.jpg ├── Defmt 单元测试.md ├── GDB调试.md ├── Linux st-link配置.md ├── Minicom使用文档.md ├── Openocd使用指南.md ├── Q&A.md ├── Renode仿真模拟.md ├── 嵌入式入门路线.md ├── 待学习案例.txt ├── 术语介绍.md └── 编译与烧录.md ├── images ├── BluePillPinout.jpg ├── minicom │ ├── 1.minicom主配置页面.png │ ├── 2.串口设置页.png │ ├── 3.串行设备配置.png │ ├── 4.波特率配置.png │ ├── 5.硬件流控制.png │ ├── 6.保存为默认设置.png │ └── 7.打开串口.png └── wiring_diagram │ ├── 10-1 软件I2C读写MPU6050.jpg │ ├── 10-2 硬件I2C读写MPU6050.jpg │ ├── 11-1 模拟SPI读写W25Q64.jpg │ ├── 11-2 硬件SPI读写W25Q64.jpg │ ├── 12-1 实时时钟.jpg │ ├── 12-2 读写备份寄存器.jpg │ ├── 13-1 修改主频.jpg │ ├── 13-2 睡眠模式+串口发送+接收.jpg │ ├── 13-3 停止模式+对射式红外传感器计次.jpg │ ├── 13-4 待机模式+实时时钟.jpg │ ├── 14-1 独立看门狗.jpg │ ├── 14-2 窗口看门狗.jpg │ ├── 15-1 读写内部FLASH.jpg │ ├── 15-2 读取芯片ID.jpg │ ├── 2-1 工程模板.jpg │ ├── 3-1 LED闪烁.jpg │ ├── 3-2 LED流水灯.jpg │ ├── 3-3 蜂鸣器.jpg │ ├── 3-4 按键控制LED.jpg │ ├── 3-5 光敏传感器控制蜂鸣器.jpg │ ├── 4-1 OLED显示屏.jpg │ ├── 5-1 对射式红外传感器计次.jpg │ ├── 5-2 旋转编码器计次.jpg │ ├── 6-1 定时器定时中断.jpg │ ├── 6-2 定时器外部时钟.jpg │ ├── 6-3 PWM驱动LED呼吸灯.jpg │ ├── 6-4 PWM驱动舵机.jpg │ ├── 6-5 PWM驱动直流电机.jpg │ ├── 6-7 PWMI模式测频率占空比.jpg │ ├── 6-8 编码器接口测速.jpg │ ├── 7-1 AD单通道.jpg │ ├── 7-2 AD多通道.jpg │ ├── 8-1 DMA数据转运.jpg │ ├── 8-2 DMA+AD多通道.jpg │ ├── 9-1 串口发送.jpg │ ├── 9-2 串口发送+接收.jpg │ ├── 9-3 串口收发HEX数据包.jpg │ ├── 9-4 串口收发文本数据包.jpg │ └── NRF24L01引脚图.jpg ├── memory.x ├── openocd.cfg ├── rust-toolchain ├── rustfmt.toml ├── scripts ├── platforms │ └── cpus │ │ └── stm32f103.repl └── stm32f103.resc └── src └── lib.rs /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.thumbv7m-none-eabi] 2 | # 真机测试 3 | # replace `$CHIP` with your chip's name (see `probe-run --list-chips` output) 4 | runner = "probe-run --chip STM32F103C8" 5 | rustflags = [ 6 | "-C", 7 | "linker=flip-link", 8 | "-C", 9 | "link-arg=-Tlink.x", 10 | # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x 11 | # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 12 | "-C", 13 | "link-arg=--nmagic", 14 | # defmt 单元测试 15 | "-C", 16 | "link-arg=-Tdefmt.x", 17 | ] 18 | 19 | 20 | [build] 21 | target = "thumbv7m-none-eabi" 22 | 23 | 24 | [alias] 25 | rb = "run --bin" 26 | rp = "run --package" 27 | rrb = "run --release --bin" 28 | rrp = "run --release --package" 29 | -------------------------------------------------------------------------------- /.cargo/config_defmt.toml: -------------------------------------------------------------------------------- 1 | [target.thumbv7m-none-eabi] 2 | # 真机测试 3 | # replace `$CHIP` with your chip's name (see `probe-run --list-chips` output) 4 | runner = "probe-run --chip STM32F103C8" 5 | rustflags = [ 6 | "-C", 7 | "linker=flip-link", 8 | "-C", 9 | "link-arg=-Tlink.x", 10 | # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x 11 | # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 12 | "-C", 13 | "link-arg=--nmagic", 14 | # defmt 单元测试 15 | "-C", 16 | "link-arg=-Tdefmt.x", 17 | ] 18 | 19 | 20 | [build] 21 | target = "thumbv7m-none-eabi" 22 | 23 | 24 | [alias] 25 | rb = "run --bin" 26 | rp = "run --package" 27 | rrb = "run --release --bin" 28 | -------------------------------------------------------------------------------- /.cargo/config_embed.toml: -------------------------------------------------------------------------------- 1 | [target.thumbv7m-none-eabi] 2 | # QEUM 3 | # runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel" 4 | # GDB 5 | # runner = 'arm-none-eabi-gdb' 6 | rustflags = [ 7 | "-C", 8 | "linker=flip-link", 9 | "-C", 10 | "link-arg=-Tlink.x", 11 | # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x 12 | # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 13 | "-C", 14 | "link-arg=--nmagic", 15 | ] 16 | 17 | 18 | [build] 19 | target = "thumbv7m-none-eabi" 20 | -------------------------------------------------------------------------------- /.cargo/config_runner_gdb.toml: -------------------------------------------------------------------------------- 1 | [target.thumbv7m-none-eabi] 2 | # GDB 3 | runner = 'arm-none-eabi-gdb' 4 | rustflags = [ 5 | "-C", 6 | "linker=flip-link", 7 | "-C", 8 | "link-arg=-Tlink.x", 9 | # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x 10 | # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 11 | "-C", 12 | "link-arg=--nmagic", 13 | ] 14 | 15 | 16 | [build] 17 | target = "thumbv7m-none-eabi" 18 | -------------------------------------------------------------------------------- /.cargo/config_runner_qeum.toml: -------------------------------------------------------------------------------- 1 | [target.thumbv7m-none-eabi] 2 | # QEUM 3 | runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel" 4 | rustflags = [ 5 | "-C", 6 | "linker=flip-link", 7 | "-C", 8 | "link-arg=-Tlink.x", 9 | # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x 10 | # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 11 | "-C", 12 | "link-arg=--nmagic", 13 | ] 14 | 15 | 16 | [build] 17 | target = "thumbv7m-none-eabi" 18 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | RUST_BACKTRACE=1 2 | RUST_LOG=debug 3 | # defmt log level 4 | DEFMT_LOG=trace 5 | -------------------------------------------------------------------------------- /.gdbinit: -------------------------------------------------------------------------------- 1 | target remote :3333 2 | 3 | monitor arm semihosting enable 4 | 5 | # # send captured ITM to the file itm.fifo 6 | # # (the microcontroller SWO pin must be connected to the programmer SWO pin) 7 | # # 8000000 must match the core clock frequency 8 | # monitor tpiu config internal itm.fifo uart off 8000000 9 | 10 | # # OR: make the microcontroller SWO pin output compatible with UART (8N1) 11 | # # 2000000 is the frequency of the SWO pin 12 | # monitor tpiu config external uart off 8000000 2000000 13 | 14 | # # enable ITM port 0 15 | # monitor itm port 0 on 16 | 17 | 18 | load 19 | step 20 | 21 | # list main 22 | 23 | # break 18 24 | 25 | # info break 26 | 27 | # continue 28 | 29 | # print x 30 | 31 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | CHANGELOG.md merge=union -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | 3 | # 仿真仓库代码 4 | scripts/renode/ 5 | 6 | # FreeRTOS 内核 7 | app/free_rtos/free_rtos_blinky/FreeRTOS-KernelV10.6.1 8 | 9 | # 临时测试代码 10 | examples/examples 11 | examples/stm32* 12 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "rust.all_targets": false, 3 | "rust.target": "thumbv7m-none-eabi", 4 | "rust.all_features": false, 5 | "rust.features": ["rtic", "stm32f103", "medium"], 6 | // "rust-analyzer.cargo.features": ["rtic", "stm32f103", "medium"], 7 | "rust-analyzer.checkOnSave.allTargets": false, 8 | "rust-analyzer.checkOnSave.extraArgs": ["--target", "thumbv7m-none-eabi"] 9 | } 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 silent rain 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /app/adc/ad_multichannel/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ad_multichannel" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | 17 | [dependencies.hardware] 18 | path = "../../../core/hardware" 19 | -------------------------------------------------------------------------------- /app/adc/ad_multichannel/README.md: -------------------------------------------------------------------------------- 1 | # AD 多通道 2 | 3 | 这是一个 AD 多通道、单次转换、非扫描模式的示例。演示使用 4 个 AD 通道,分别接入电位器、光敏传感器、热敏传感器、反射式红外传感器。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp ad_multichannel 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解多通道取值 14 | 15 | ## 接线图 16 | 17 | ![](../../../images/wiring_diagram/7-2%20AD多通道.jpg) 18 | -------------------------------------------------------------------------------- /app/adc/ad_single_channel/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ad_single_channel" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/adc/ad_single_channel/README.md: -------------------------------------------------------------------------------- 1 | # AD 单通道 2 | 3 | 这是一个 AD 单通道、单次转换、非扫描模式的示例。演示使用电位器来模拟电压。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp ad_single_channel 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解 ADC 14 | - 了解 DAC 15 | - 了解电位器 16 | 17 | ## 接线图 18 | 19 | ![](../../../images/wiring_diagram/7-1%20AD单通道.jpg) 20 | -------------------------------------------------------------------------------- /app/basic/flash_tool_defmt/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.thumbv7m-none-eabi] 2 | # 真机测试 3 | # replace `$CHIP` with your chip's name (see `probe-run --list-chips` output) 4 | runner = "probe-run --chip STM32F103C8" 5 | rustflags = [ 6 | "-C", 7 | "linker=flip-link", 8 | "-C", 9 | "link-arg=-Tlink.x", 10 | # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x 11 | # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 12 | "-C", 13 | "link-arg=--nmagic", 14 | # defmt 单元测试 15 | "-C", 16 | "link-arg=-Tdefmt.x", 17 | ] 18 | 19 | 20 | [build] 21 | target = "thumbv7m-none-eabi" 22 | 23 | 24 | [alias] 25 | rb = "run --bin" 26 | rp = "run --package" 27 | rrb = "run --release --bin" 28 | -------------------------------------------------------------------------------- /app/basic/flash_tool_defmt/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "flash_tool_defmt" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dev-dependencies] 17 | defmt-test = "0.3.0" 18 | -------------------------------------------------------------------------------- /app/basic/flash_tool_defmt/README.md: -------------------------------------------------------------------------------- 1 | # 烧录工具 probe-run 2 | 3 | 这是一个使用 probe-run 命令来处理嵌入式目标的示例。在这里也会了解到使用 defmt 进行终端打印的用法。 4 | 5 | 在工作空间中执行需要将 `.cargo/config_defmt.toml` 替换为 `.cargo/config.toml` 文件。 6 | 7 | ## 执行指令 8 | 9 | ```shell 10 | cargo rp flash_tool_defmt 11 | # or 12 | DEFMT_LOG=trace cargo rp flash_tool_defmt 13 | ``` 14 | 15 | ## 学习目标 16 | 17 | - 了解 probe-run 配置 18 | - 了解 probe-run 烧录命令 19 | - 了解 Defmt RTT 终端打印 20 | -------------------------------------------------------------------------------- /app/basic/flash_tool_defmt/build.rs: -------------------------------------------------------------------------------- 1 | //! This build script copies the `memory.x` file from the crate root into 2 | //! a directory where the linker can always find it at build time. 3 | //! For many projects this is optional, as the linker always searches the 4 | //! project root directory -- wherever `Cargo.toml` is. However, if you 5 | //! are using a workspace or have a more complicated build setup, this 6 | //! build script becomes required. Additionally, by requesting that 7 | //! Cargo re-run the build script whenever `memory.x` is changed, 8 | //! updating `memory.x` ensures a rebuild of the application with the 9 | //! new memory settings. 10 | 11 | use std::env; 12 | use std::fs::File; 13 | use std::io::Write; 14 | use std::path::PathBuf; 15 | 16 | fn main() { 17 | // Put `memory.x` in our output directory and ensure it's 18 | // on the linker search path. 19 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 20 | File::create(out.join("memory.x")) 21 | .unwrap() 22 | .write_all(include_bytes!("memory.x")) 23 | .unwrap(); 24 | println!("cargo:rustc-link-search={}", out.display()); 25 | 26 | // By default, Cargo will re-run a build script whenever 27 | // any file in the project changes. By specifying `memory.x` 28 | // here, we ensure the build script is only re-run when 29 | // `memory.x` is changed. 30 | println!("cargo:rerun-if-changed=memory.x"); 31 | } 32 | -------------------------------------------------------------------------------- /app/basic/flash_tool_defmt/memory.x: -------------------------------------------------------------------------------- 1 | /* Linker script for the STM32F103C8T6 */ 2 | MEMORY 3 | { 4 | FLASH : ORIGIN = 0x08000000, LENGTH = 64K 5 | RAM : ORIGIN = 0x20000000, LENGTH = 20K 6 | } -------------------------------------------------------------------------------- /app/basic/flash_tool_defmt/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | // 标记该程序没有使用标准的 main 函数作为程序入口; 3 | #![no_main] 4 | // 允许有空的循环结构; 5 | #![allow(clippy::empty_loop)] 6 | // 禁止使用 Rust 的 unsafe 代码; 7 | #![deny(unsafe_code)] 8 | 9 | // 用于处理错误情况; 10 | use panic_probe as _; 11 | // global logger 12 | use defmt_rtt as _; 13 | 14 | // adjust HAL import 15 | use stm32f1xx_hal as _; // memory layout 16 | 17 | // 用于标记程序入口; 18 | use cortex_m_rt::entry; 19 | 20 | // 标记接下来的函数是程序的入口点; 21 | // fn main() -> ! 定义程序的入口函数 main,返回类型为 `!`,表示这个函数不应该返回; 22 | #[entry] 23 | fn main() -> ! { 24 | // _y 的可变变量,但未初始化; 25 | let mut _y; 26 | // 定义变量 x,并将其值设置为 42; 27 | let x = 42; 28 | // 将变量 x 的值赋给 _y; 29 | _y = x; 30 | // 通过 OpenOCD 终端输出 `_y` 变量的值,使用十六进制表示; 31 | defmt::println!("_y={:?}", _y); 32 | defmt::println!("x={=u8}", x); 33 | 34 | // try setting the DEFMT_LOG environment variable 35 | // e.g. `export DEFMT_LOG=info` or `DEFMT_LOG=trace cargo rb levels` 36 | defmt::trace!("trace"); 37 | defmt::debug!("debug"); 38 | defmt::info!("info"); 39 | defmt::warn!("warn"); 40 | defmt::error!("error"); 41 | 42 | // 进入一个空的无限循环,防止程序异常退出。 43 | loop {} 44 | } 45 | -------------------------------------------------------------------------------- /app/basic/flash_tool_embed/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.thumbv7m-none-eabi] 2 | # QEUM 3 | # runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel" 4 | # GDB 5 | # runner = 'arm-none-eabi-gdb' 6 | rustflags = [ 7 | "-C", 8 | "linker=flip-link", 9 | "-C", 10 | "link-arg=-Tlink.x", 11 | # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x 12 | # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 13 | "-C", 14 | "link-arg=--nmagic", 15 | ] 16 | 17 | 18 | [build] 19 | target = "thumbv7m-none-eabi" 20 | -------------------------------------------------------------------------------- /app/basic/flash_tool_embed/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "flash_tool_embed" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | # Panic behaviour, see https://crates.io/keywords/panic-impl for alternatives 13 | # panic-halt = "0.2.0" 14 | rtt-target = {version = "0.4.0", features = []} 15 | panic-rtt-target = {version = "0.1.2", features = ["cortex-m"]} 16 | -------------------------------------------------------------------------------- /app/basic/flash_tool_embed/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.general] 14 | chip = "STM32F103C8" 15 | 16 | # [default.reset] 17 | # halt_afterwards = true 18 | 19 | [default.rtt] 20 | enabled = true 21 | 22 | [default.gdb] 23 | enabled = false 24 | -------------------------------------------------------------------------------- /app/basic/flash_tool_embed/README.md: -------------------------------------------------------------------------------- 1 | # 烧录工具 Embed 2 | 3 | 这是一个使用 Embed 命令来处理嵌入式目标的示例。 4 | 5 | 在工作空间中执行需要将 `.cargo/config_embed.toml` 替换为 `.cargo/config.toml` 文件。 6 | 7 | 如果需要打印信息到终端注意配置 `Embed.toml` 文件。 8 | 9 | ## 执行指令 10 | 11 | ```shell 12 | cargo embed --target thumbv7m-none-eabi -p flash_tool_embed 13 | ``` 14 | 15 | ## 学习目标 16 | 17 | - 了解 Embed 配置 18 | - 了解 Embed 烧录命令 19 | - 了解 RTT 终端打印 20 | -------------------------------------------------------------------------------- /app/basic/flash_tool_embed/build.rs: -------------------------------------------------------------------------------- 1 | //! This build script copies the `memory.x` file from the crate root into 2 | //! a directory where the linker can always find it at build time. 3 | //! For many projects this is optional, as the linker always searches the 4 | //! project root directory -- wherever `Cargo.toml` is. However, if you 5 | //! are using a workspace or have a more complicated build setup, this 6 | //! build script becomes required. Additionally, by requesting that 7 | //! Cargo re-run the build script whenever `memory.x` is changed, 8 | //! updating `memory.x` ensures a rebuild of the application with the 9 | //! new memory settings. 10 | 11 | use std::env; 12 | use std::fs::File; 13 | use std::io::Write; 14 | use std::path::PathBuf; 15 | 16 | fn main() { 17 | // Put `memory.x` in our output directory and ensure it's 18 | // on the linker search path. 19 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 20 | File::create(out.join("memory.x")) 21 | .unwrap() 22 | .write_all(include_bytes!("memory.x")) 23 | .unwrap(); 24 | println!("cargo:rustc-link-search={}", out.display()); 25 | 26 | // By default, Cargo will re-run a build script whenever 27 | // any file in the project changes. By specifying `memory.x` 28 | // here, we ensure the build script is only re-run when 29 | // `memory.x` is changed. 30 | println!("cargo:rerun-if-changed=memory.x"); 31 | } 32 | -------------------------------------------------------------------------------- /app/basic/flash_tool_embed/memory.x: -------------------------------------------------------------------------------- 1 | /* Linker script for the STM32F103C8T6 */ 2 | MEMORY 3 | { 4 | FLASH : ORIGIN = 0x08000000, LENGTH = 64K 5 | RAM : ORIGIN = 0x20000000, LENGTH = 20K 6 | } -------------------------------------------------------------------------------- /app/basic/flash_tool_embed/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | // 标记该程序没有使用标准的 main 函数作为程序入口; 3 | #![no_main] 4 | // 允许有空的循环结构; 5 | #![allow(clippy::empty_loop)] 6 | // 禁止使用 Rust 的 unsafe 代码; 7 | #![deny(unsafe_code)] 8 | 9 | // 用于处理错误情况; 10 | // use panic_halt as _; 11 | use panic_rtt_target as _; 12 | use rtt_target::{rprintln, rtt_init_print}; 13 | 14 | // 用于标记程序入口; 15 | use cortex_m_rt::entry; 16 | use stm32f1xx_hal as _; 17 | 18 | // 标记接下来的函数是程序的入口点; 19 | // fn main() -> ! 定义程序的入口函数 main,返回类型为 `!`,表示这个函数不应该返回; 20 | #[entry] 21 | fn main() -> ! { 22 | rtt_init_print!(); 23 | 24 | // _y 的可变变量,但未初始化; 25 | let mut _y; 26 | // 定义变量 x,并将其值设置为 42; 27 | let x = 42; 28 | // 将变量 x 的值赋给 _y; 29 | _y = x; 30 | // 通过 OpenOCD 终端输出 `_y` 变量的值,使用十六进制表示; 31 | rprintln!("_y={:?}", _y); 32 | rprintln!("x={:?}", x); 33 | 34 | // 进入一个空的无限循环,防止程序异常退出。 35 | loop {} 36 | } 37 | -------------------------------------------------------------------------------- /app/basic/helloworld/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "helloworld" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | [dependencies] 8 | cortex-m-rt = "0.7.3" 9 | panic-semihosting = "0.6.0" 10 | cortex-m-semihosting = "0.5.0" 11 | -------------------------------------------------------------------------------- /app/basic/helloworld/README.md: -------------------------------------------------------------------------------- 1 | # Hello World 2 | 3 | 这个是一个简单的 Hello World 示例。 4 | 5 | ## 学习目标 6 | 7 | - 了解项目结构 8 | - 项目配置了解 9 | - 了解项目编译目标的配置 `.cargo/config.toml` 10 | - 了解 vscode 的配置, 用于消除编译器告警 `.vscode/settings.json` 11 | - 了解工作空间配置 `Cargo.toml` 12 | - 了解 GDB 调试的自动接入脚本 `.gdbinit` 13 | - 了解 Renode 仿真模拟器的配置 `scripts/stm32f103.resc` 14 | - 编译 15 | - debug 编译 16 | - release 编译 17 | - Renode 仿真模拟器的使用 18 | - Renode CLI 启动 19 | - stm32 仿真器启动 20 | - QEUM 仿真器的使用 21 | - GDB 调试 22 | - GDB 手动启动 23 | - GDB 自动化脚本启动 24 | - 调试与打印代码中的变量 25 | -------------------------------------------------------------------------------- /app/basic/helloworld/src/main.rs: -------------------------------------------------------------------------------- 1 | //! Prints "Hello, world" on the OpenOCD console 2 | #![no_std] 3 | // 标记该程序没有使用标准的 main 函数作为程序入口; 4 | #![no_main] 5 | // 允许有空的循环结构; 6 | #![allow(clippy::empty_loop)] 7 | // 禁止使用 Rust 的 unsafe 代码; 8 | #![deny(unsafe_code)] 9 | 10 | // 用于处理错误情况; 11 | use panic_semihosting as _; 12 | 13 | // 便于程序调试; 14 | use cortex_m_semihosting::debug; 15 | // 用于在 OpenOCD 终端上输出信息; 16 | use cortex_m_semihosting::hprintln; 17 | // 用于标记程序入口; 18 | use cortex_m_rt::entry; 19 | 20 | // 标记接下来的函数是程序的入口点; 21 | // fn main() -> ! 定义程序的入口函数 main,返回类型为 `!`,表示这个函数不应该返回; 22 | #[entry] 23 | fn main() -> ! { 24 | // _y 的可变变量,但未初始化; 25 | let mut _y; 26 | // 定义变量 x,并将其值设置为 42; 27 | let x = 42; 28 | // 将变量 x 的值赋给 _y; 29 | _y = x; 30 | // 通过 OpenOCD 终端输出 `_y` 变量的值,使用十六进制表示; 31 | hprintln!("y: {:#?}", _y); 32 | // 通过 OpenOCD 终端输出 "Hello, world!"; 33 | hprintln!("Hello, world!"); 34 | 35 | // 退出 Renode 36 | // 执行到此处时通知 OpenOCD 结束程序,并返回正常退出状态。 37 | // 注意不要在实际硬件上运行这一行代码,它会导致 OpenOCD 失败; 38 | debug::exit(debug::EXIT_SUCCESS); 39 | 40 | // 进入一个空的无限循环,防止程序异常退出。 41 | loop {} 42 | } 43 | -------------------------------------------------------------------------------- /app/basic/panics/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "panics" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | [dependencies] 8 | cortex-m-rt = "0.7.3" 9 | panic-semihosting = "0.6.0" 10 | cortex-m-semihosting = "0.5.0" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | -------------------------------------------------------------------------------- /app/basic/panics/README.md: -------------------------------------------------------------------------------- 1 | # 自定义异常 Panic 2 | 3 | 这个是一个简单的自定义异常 Panics 示例。 4 | 5 | 在 OpenOCD 控制台上打印“你好,世界”。 6 | 7 | 这里例子来自依赖库的官方案例。 8 | 9 | ## 学习目标 10 | 11 | - 了解自定义异常 12 | - 在控制台打印字符串 13 | -------------------------------------------------------------------------------- /app/basic/panics/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![allow(clippy::empty_loop)] 4 | 5 | use panic_semihosting as _; 6 | //use panic_itm as _; 7 | use cortex_m_semihosting::hprintln; 8 | use stm32f1xx_hal as _; 9 | 10 | use cortex_m_rt::{entry, exception, ExceptionFrame}; 11 | 12 | #[entry] 13 | fn main() -> ! { 14 | hprintln!("Hello, world!"); 15 | loop {} 16 | } 17 | 18 | #[exception] 19 | unsafe fn HardFault(ef: &ExceptionFrame) -> ! { 20 | panic!("{:#?}", ef); 21 | } 22 | 23 | #[exception] 24 | unsafe fn DefaultHandler(irqn: i16) { 25 | panic!("Unhandled exception (IRQn = {})", irqn); 26 | } 27 | -------------------------------------------------------------------------------- /app/basic/unit_testsuite/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "unit_testsuite" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | 7 | [lib] 8 | harness = false 9 | 10 | 11 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 12 | [dependencies] 13 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 14 | cortex-m-rt = "0.7.3" 15 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 16 | defmt = "0.3" 17 | defmt-rtt = "0.4.0" 18 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 19 | 20 | [dev-dependencies] 21 | defmt-test = "0.3.0" 22 | -------------------------------------------------------------------------------- /app/basic/unit_testsuite/README.md: -------------------------------------------------------------------------------- 1 | # 单元测试套件 2 | 3 | 这是一个单元测试套件的使用案例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo test --target thumbv7m-none-eabi -p unit_testsuite 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解嵌入式的单元测试 14 | 15 | ## 相关文档 16 | 17 | - [defmt-test 测试用例](https://github.com/fkohlgrueber/atat-blue-pill) 18 | -------------------------------------------------------------------------------- /app/basic/unit_testsuite/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use defmt_rtt as _; // global logger 5 | 6 | // adjust HAL import 7 | use stm32f1xx_hal as _; // memory layout 8 | 9 | use panic_probe as _; 10 | 11 | // defmt-test 0.3.0 has the limitation that this `#[tests]` attribute can only be used 12 | // once within a crate. the module can be in any file but there can only be at most 13 | // one `#[tests]` module in this library crate 14 | #[cfg(test)] 15 | #[defmt_test::tests] 16 | mod unit_tests { 17 | use defmt::assert; 18 | 19 | #[test] 20 | fn it_works() { 21 | assert!(true) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/delay/asm_delay/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "asm_delay" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | -------------------------------------------------------------------------------- /app/delay/asm_delay/README.md: -------------------------------------------------------------------------------- 1 | # 汇编延迟 2 | 3 | 这是一个在汇编中实现的,因此它的执行时间与优化级别无关,但它取决于特定的体系结构和核心配置的示例。 4 | 5 | 请注意,如果中断在执行期间得到服务,则延迟可能需要更长的时间,并且执行时间可能因其他因素而异。如果并且仅当准确的定时不是必要的时,这种延迟主要用于外围设备的简单无定时器初始化。在任何其他情况下,请使用更准确的方法来产生延迟。 6 | 7 | ## 执行指令 8 | 9 | ```shell 10 | cargo rp asm_delay 11 | ``` 12 | 13 | ## 学习目标 14 | 15 | - 了解汇编延迟的用法 16 | -------------------------------------------------------------------------------- /app/delay/asm_delay/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![deny(unsafe_code)] 4 | 5 | use cortex_m::asm; 6 | use defmt::println; 7 | use defmt_rtt as _; 8 | use panic_probe as _; 9 | 10 | use cortex_m_rt::entry; 11 | use stm32f1xx_hal::pac; 12 | use stm32f1xx_hal::prelude::_stm32_hal_flash_FlashExt; 13 | use stm32f1xx_hal::rcc::RccExt; 14 | 15 | #[entry] 16 | fn main() -> ! { 17 | // 获取对外设的访问对象 18 | let dp = pac::Peripherals::take().unwrap(); 19 | 20 | // 获得原始flash和rcc设备的所有权,并将它们转换为相应的HAL结构 21 | let mut flash = dp.FLASH.constrain(); 22 | let rcc = dp.RCC.constrain(); 23 | 24 | // 冻结系统中所有时钟的配置,并将冻结的频率存储在时钟中 25 | let _clocks = rcc.cfgr.freeze(&mut flash.acr); 26 | 27 | // 等待计时器触发更新并更改LED的状态 28 | loop { 29 | for i in 0..10 { 30 | println!("i={:?}", i); 31 | // 延时一秒 32 | asm::delay(8_000_000); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/delay/syst_delay/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "syst_delay" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | -------------------------------------------------------------------------------- /app/delay/syst_delay/README.md: -------------------------------------------------------------------------------- 1 | # 系统定时器延迟 2 | 3 | 这是一个使用系统定时器延迟打印数字的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp syst_delay 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解系统定时器延迟的用法 14 | -------------------------------------------------------------------------------- /app/delay/syst_delay/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![deny(unsafe_code)] 4 | 5 | use defmt::println; 6 | use defmt_rtt as _; 7 | use panic_probe as _; 8 | 9 | use cortex_m::prelude::_embedded_hal_blocking_delay_DelayMs; 10 | use cortex_m_rt::entry; 11 | use stm32f1xx_hal::pac; 12 | use stm32f1xx_hal::prelude::_fugit_ExtU32; 13 | use stm32f1xx_hal::prelude::_stm32_hal_flash_FlashExt; 14 | use stm32f1xx_hal::rcc::RccExt; 15 | use stm32f1xx_hal::timer::SysTimerExt; 16 | 17 | #[entry] 18 | fn main() -> ! { 19 | // 获取对外设的访问对象 20 | let cp = cortex_m::Peripherals::take().unwrap(); 21 | let dp = pac::Peripherals::take().unwrap(); 22 | 23 | // 获得原始flash和rcc设备的所有权,并将它们转换为相应的HAL结构 24 | let mut flash = dp.FLASH.constrain(); 25 | let rcc = dp.RCC.constrain(); 26 | 27 | // 冻结系统中所有时钟的配置,并将冻结的频率存储在时钟中 28 | let clocks = rcc.cfgr.freeze(&mut flash.acr); 29 | 30 | // 具有自定义精度的阻塞延迟 31 | let mut delay = cp.SYST.delay(&clocks); 32 | 33 | // 等待计时器触发更新并更改LED的状态 34 | loop { 35 | for i in 0..10 { 36 | println!("i={:?}", i); 37 | // Use `embedded_hal::DelayMs` trait 38 | delay.delay_ms(1_000_u16); 39 | } 40 | // or use `fugit` duration units 41 | delay.delay(1.secs()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/delay/syst_timer_delay/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "syst_timer_delay" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | nb = "1" 16 | -------------------------------------------------------------------------------- /app/delay/syst_timer_delay/README.md: -------------------------------------------------------------------------------- 1 | # 系统计时器延迟 2 | 3 | 这是一个使用内部计时器延迟打印数字的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp syst_timer_delay 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解系统计时器延迟的用法 14 | -------------------------------------------------------------------------------- /app/delay/syst_timer_delay/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![deny(unsafe_code)] 4 | 5 | use defmt_rtt as _; 6 | use panic_probe as _; 7 | 8 | use cortex_m_rt::entry; 9 | use defmt::println; 10 | use nb::block; 11 | use stm32f1xx_hal::pac; 12 | use stm32f1xx_hal::prelude::_fugit_RateExtU32; 13 | use stm32f1xx_hal::prelude::_stm32_hal_flash_FlashExt; 14 | use stm32f1xx_hal::rcc::RccExt; 15 | use stm32f1xx_hal::timer::Timer; 16 | 17 | #[entry] 18 | fn main() -> ! { 19 | // 获取对外设的访问对象 20 | let cp = cortex_m::Peripherals::take().unwrap(); 21 | let dp = pac::Peripherals::take().unwrap(); 22 | 23 | // 获得原始flash和rcc设备的所有权,并将它们转换为相应的HAL结构 24 | let mut flash = dp.FLASH.constrain(); 25 | let rcc = dp.RCC.constrain(); 26 | 27 | // 冻结系统中所有时钟的配置,并将冻结的频率存储在时钟中 28 | let clocks = rcc.cfgr.freeze(&mut flash.acr); 29 | 30 | // 将系统计时器配置为每秒触发一次更新 31 | let mut timer = Timer::syst(cp.SYST, &clocks).counter_hz(); 32 | timer.start(1.Hz()).unwrap(); 33 | 34 | // 等待计时器触发更新并更改LED的状态 35 | loop { 36 | for i in 0..10 { 37 | println!("i={:?}", i); 38 | block!(timer.wait()).unwrap(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/delay/tim2_delay/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tim2_delay" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | -------------------------------------------------------------------------------- /app/delay/tim2_delay/README.md: -------------------------------------------------------------------------------- 1 | # TIM2 定时器延迟 2 | 3 | 这是一个使用 TIM2 定时器延迟打印数字的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp tim2_delay 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解 TIM2 定时器延迟的用法 14 | -------------------------------------------------------------------------------- /app/delay/tim2_delay/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![deny(unsafe_code)] 4 | 5 | use defmt::println; 6 | use defmt_rtt as _; 7 | use panic_probe as _; 8 | 9 | use cortex_m::prelude::_embedded_hal_blocking_delay_DelayMs; 10 | use cortex_m_rt::entry; 11 | use stm32f1xx_hal::pac; 12 | use stm32f1xx_hal::prelude::_fugit_ExtU32; 13 | use stm32f1xx_hal::prelude::_stm32_hal_flash_FlashExt; 14 | use stm32f1xx_hal::rcc::RccExt; 15 | use stm32f1xx_hal::timer::TimerExt; 16 | 17 | #[entry] 18 | fn main() -> ! { 19 | // 获取对外设的访问对象 20 | let dp = pac::Peripherals::take().unwrap(); 21 | 22 | // 获得原始flash和rcc设备的所有权,并将它们转换为相应的HAL结构 23 | let mut flash = dp.FLASH.constrain(); 24 | let rcc = dp.RCC.constrain(); 25 | 26 | // 冻结系统中所有时钟的配置,并将冻结的频率存储在时钟中 27 | let clocks = rcc.cfgr.freeze(&mut flash.acr); 28 | 29 | // 基于通用pupose 32位定时器TIM2创建延迟抽象 30 | 31 | //let mut delay = hal::timer::FTimerUs::new(dp.TIM2, &clocks).delay(); 32 | // or 33 | let mut delay = dp.TIM2.delay_us(&clocks); 34 | 35 | // 等待计时器触发更新并更改LED的状态 36 | loop { 37 | for i in 0..10 { 38 | println!("i={:?}", i); 39 | // Use `embedded_hal::DelayMs` trait 40 | delay.delay_ms(1000_u32); 41 | } 42 | // or use `fugit` duration units 43 | delay.delay(3.secs()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/dma/dma_data_continuous_transfer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dma_data_continuous_transfer" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | embedded-dma = "0.2.0" 16 | 17 | [dependencies.hardware] 18 | path = "../../../core/hardware" 19 | -------------------------------------------------------------------------------- /app/dma/dma_data_continuous_transfer/README.md: -------------------------------------------------------------------------------- 1 | # DMA 数据连续转运 2 | 3 | 这是一个 DMA 数据连续转运的示例。演示循环将数组 data_a 的数据转运到 data_b,同时更新 data_a 的数据。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp dma_data_continuous_transfer 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解 DMA 14 | -------------------------------------------------------------------------------- /app/dma/dma_data_transfer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dma_data_transfer" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | embedded-dma = "0.2.0" 16 | 17 | [dependencies.hardware] 18 | path = "../../../core/hardware" 19 | -------------------------------------------------------------------------------- /app/dma/dma_data_transfer/README.md: -------------------------------------------------------------------------------- 1 | # DMA 数据转运 2 | 3 | 这是一个 DMA 数据转运的示例。演示将数组 data_a 的数据转运到 data_b。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp dma_data_transfer 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解 DMA 14 | - 存储器到存储器转运 15 | - Flash 到 SRAM 转运 16 | -------------------------------------------------------------------------------- /app/dma/print_memory_address/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "print_memory_address" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/dma/print_memory_address/README.md: -------------------------------------------------------------------------------- 1 | # 打印内存地址 2 | 3 | 这是一个打印内存地址的示例。演示变量、常量、外设寄存器地址所在的地址映射范围。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp print_memory_address 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解存储器映像 14 | -------------------------------------------------------------------------------- /app/dma/scan_dma_and_ad_multichannel/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "scan_dma_and_ad_multichannel" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | embedded-dma = "0.2.0" 16 | 17 | [dependencies.hardware] 18 | path = "../../../core/hardware" 19 | -------------------------------------------------------------------------------- /app/dma/scan_dma_and_ad_multichannel/README.md: -------------------------------------------------------------------------------- 1 | # DMA+AD 多通道 2 | 3 | 这是一个 DMA+AD 多通道的示例。使用 ADC 的扫描模式加 DMA 数据转运。以阻塞的方式读取数据。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp scan_dma_and_ad_multichannel 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解 DMA 14 | 15 | ## 接线图 16 | 17 | ![](../../../images/wiring_diagram/8-2%20DMA+AD多通道.jpg) 18 | -------------------------------------------------------------------------------- /app/dma/scan_dma_and_ad_multichannel_loop/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "scan_dma_and_ad_multichannel_loop" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | embedded-dma = "0.2.0" 16 | 17 | [dependencies.hardware] 18 | path = "../../../core/hardware" 19 | -------------------------------------------------------------------------------- /app/dma/scan_dma_and_ad_multichannel_loop/README.md: -------------------------------------------------------------------------------- 1 | # DMA+AD 多通道循环读取 2 | 3 | 这是一个 DMA+AD 多通道的示例。使用 ADC 的扫描模式加 DMA 数据转运,循环读取数据。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp scan_dma_and_ad_multichannel_loop 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解 DMA 14 | 15 | ## 接线图 16 | 17 | ![](../../../images/wiring_diagram/8-2%20DMA+AD多通道.jpg) 18 | -------------------------------------------------------------------------------- /app/dma/scan_dma_and_ad_multichannel_peek/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "scan_dma_and_ad_multichannel_peek" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | embedded-dma = "0.2.0" 16 | 17 | 18 | [dependencies.hardware] 19 | path = "../../../core/hardware" 20 | -------------------------------------------------------------------------------- /app/dma/scan_dma_and_ad_multichannel_peek/README.md: -------------------------------------------------------------------------------- 1 | # DMA+AD 多通道分批读取 2 | 3 | 这是一个 DMA+AD 多通道的示例。使用 ADC 的扫描模式加 DMA 数据转运。以阻塞的方式读取数据。ADC 接口循环 DMA RX 传输测试 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp scan_dma_and_ad_multichannel_peek 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解 DMA 14 | 15 | ## 接线图 16 | 17 | ![](../../../images/wiring_diagram/8-2%20DMA+AD多通道.jpg) 18 | -------------------------------------------------------------------------------- /app/flash/internal_flash/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "internal_flash" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | embedded-dma = "0.2.0" 16 | nb = "1.1.0" 17 | unwrap-infallible = "0.1.5" 18 | heapless = "0.8.0" 19 | 20 | [dependencies.hardware] 21 | path = "../../../core/hardware" 22 | -------------------------------------------------------------------------------- /app/flash/internal_flash/README.md: -------------------------------------------------------------------------------- 1 | # 读写内部 FLASH 2 | 3 | 这是一个读写内部 FLASH 的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp internal_flash 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解内部 FLASH 14 | 15 | ## 接线图 16 | 17 | ![](../../../images/wiring_diagram/15-1%20读写内部FLASH.jpg) 18 | -------------------------------------------------------------------------------- /app/flash/read_chip_id/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "read_chip_id" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = { version = "0.10.0", features = ["rt", "stm32f103", "medium"] } 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = { version = "0.3.1", features = ["print-defmt"] } 15 | embedded-dma = "0.2.0" 16 | nb = "1.1.0" 17 | unwrap-infallible = "0.1.5" 18 | heapless = "0.8.0" 19 | 20 | [dependencies.hardware] 21 | path = "../../../core/hardware" 22 | -------------------------------------------------------------------------------- /app/flash/read_chip_id/README.md: -------------------------------------------------------------------------------- 1 | # 读取芯片 ID 2 | 3 | 这是一个操作裸指针读取芯片 ID 的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp read_chip_id 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 操作裸指针读取数据 14 | 15 | ## 接线图 16 | 17 | ![](../../../images/wiring_diagram/15-2%20读取芯片ID.jpg) 18 | -------------------------------------------------------------------------------- /app/free_rtos/free_rtos_blinky/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "free_rtos_blinky" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | freertos-rust = "0.1.2" 16 | 17 | [build-dependencies] 18 | freertos-cargo-build = "0.1.1" 19 | -------------------------------------------------------------------------------- /app/free_rtos/free_rtos_blinky/README.md: -------------------------------------------------------------------------------- 1 | # FreeRTOS-闪烁 LED 2 | 3 | 这是一个 FreeRTOS 闪烁 LED 的示例。是一个实验性质的示例,暂时不可用,需要 nightly 版本才可以运行。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | # 下载内核 9 | wget https://github.com/FreeRTOS/FreeRTOS-Kernel/releases/download/V10.6.1/FreeRTOS-KernelV10.6.1.zip 10 | unzip FreeRTOS-KernelV10.6.1.zip 11 | 12 | # run 13 | cargo rp free_rtos_blinky 14 | ``` 15 | 16 | ## 学习目标 17 | 18 | - 配置与使用 FreeRTOS 19 | 20 | ## 接线图 21 | 22 | ![](../../../images/wiring_diagram/3-1%20LED闪烁.jpg) 23 | 24 | ## 参考 25 | 26 | - [FreeRTOS-Kernel](https://github.com/FreeRTOS/FreeRTOS-Kernel/releases/tag/V10.6.1) 27 | - [FreeRTOS-KernelV10.6.1 下载](https://github.com/FreeRTOS/FreeRTOS-Kernel/releases/download/V10.6.1/FreeRTOS-KernelV10.6.1.zip) 28 | -------------------------------------------------------------------------------- /app/free_rtos/free_rtos_blinky/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut b = freertos_cargo_build::Builder::new(); 3 | 4 | // Path to FreeRTOS kernel or set ENV "FREERTOS_SRC" instead 5 | b.freertos("./FreeRTOS-KernelV10.6.1"); 6 | // Location of `FreeRTOSConfig.h` 7 | b.freertos_config("src"); 8 | // Port dir relativ to 'FreeRTOS-Kernel/portable' 9 | b.freertos_port("GCC/ARM_CM3".to_owned()); 10 | // Set the heap_?.c allocator to use from 11 | // 'FreeRTOS-Kernel/portable/MemMang' (Default: heap_4.c) 12 | b.heap::<&str>("heap_4.c".to_owned()); 13 | // Optional additional C-Code to be compiled 14 | // b.get_cc().file("More.c"); 15 | 16 | b.compile().unwrap_or_else(|e| panic!("{}", e.to_string())); 17 | } 18 | -------------------------------------------------------------------------------- /app/general_gpio/blinky/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blinky" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | nb = "1" 16 | -------------------------------------------------------------------------------- /app/general_gpio/blinky/README.md: -------------------------------------------------------------------------------- 1 | # 闪烁 LED 2 | 3 | 这是一个持续闪烁 LED 灯的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp blinky 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 设置定时器 14 | - 设置高电平 15 | - 设置低电平 16 | 17 | ## 接线图 18 | 19 | ![](../../../images/wiring_diagram/3-1%20LED闪烁.jpg) 20 | -------------------------------------------------------------------------------- /app/general_gpio/buzzer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "buzzer" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | nb = "1" 16 | -------------------------------------------------------------------------------- /app/general_gpio/buzzer/README.md: -------------------------------------------------------------------------------- 1 | # 蜂鸣器 2 | 3 | 这是一个蜂鸣器的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp buzzer 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 熟悉基本用法 14 | 15 | ## 接线图 16 | 17 | ![](../../../images/wiring_diagram/3-3%20蜂鸣器.jpg) 18 | -------------------------------------------------------------------------------- /app/general_gpio/buzzer/src/main.rs: -------------------------------------------------------------------------------- 1 | //! 蜂鸣器 2 | 3 | #![no_std] 4 | #![no_main] 5 | #![deny(unsafe_code)] 6 | 7 | use defmt_rtt as _; 8 | use panic_probe as _; 9 | 10 | use cortex_m::prelude::_embedded_hal_blocking_delay_DelayMs; 11 | use cortex_m_rt::entry; 12 | use stm32f1xx_hal::gpio::IOPinSpeed; 13 | use stm32f1xx_hal::gpio::OutputSpeed; 14 | use stm32f1xx_hal::pac; 15 | use stm32f1xx_hal::prelude::_fugit_ExtU32; 16 | use stm32f1xx_hal::prelude::_stm32_hal_flash_FlashExt; 17 | use stm32f1xx_hal::prelude::_stm32_hal_gpio_GpioExt; 18 | use stm32f1xx_hal::rcc::RccExt; 19 | use stm32f1xx_hal::timer::SysTimerExt; 20 | 21 | #[entry] 22 | fn main() -> ! { 23 | // 获取对外设的访问对象 24 | let cp = cortex_m::Peripherals::take().unwrap(); 25 | let dp = pac::Peripherals::take().unwrap(); 26 | 27 | // 获得原始flash和rcc设备的所有权,并将它们转换为相应的HAL结构 28 | let mut flash = dp.FLASH.constrain(); 29 | let rcc = dp.RCC.constrain(); 30 | 31 | // 冻结系统中所有时钟的配置,并将冻结的频率存储在时钟中 32 | let clocks = rcc.cfgr.freeze(&mut flash.acr); 33 | 34 | // 获取GPIO外围设备 35 | let mut gpiob = dp.GPIOB.split(); 36 | 37 | // 将 pin 12 引脚配置为推挽式输出。 38 | let mut buzzer = gpiob.pb12.into_push_pull_output(&mut gpiob.crh); 39 | // 设置其输出速度(50 MHz)。 40 | buzzer.set_speed(&mut gpiob.crh, IOPinSpeed::Mhz50); 41 | 42 | // 具有自定义精度的阻塞延迟 43 | let mut delay = cp.SYST.delay(&clocks); 44 | 45 | // 等待计时器触发更新并更改引脚的状态 46 | loop { 47 | buzzer.set_low(); 48 | delay.delay_ms(500_u16); 49 | buzzer.set_high(); 50 | delay.delay(1.secs()); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/general_gpio/delay_blinky/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "delay_blinky" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | nb = "1" 16 | -------------------------------------------------------------------------------- /app/general_gpio/delay_blinky/README.md: -------------------------------------------------------------------------------- 1 | # 延迟闪烁 LED 2 | 3 | 这是一个具有自定义精度的阻塞延迟的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp delay_blinky 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 熟悉延迟的用法 14 | -------------------------------------------------------------------------------- /app/general_gpio/delay_blinky/src/main.rs: -------------------------------------------------------------------------------- 1 | //! "Blinky" using delays instead of a timer 2 | 3 | #![no_std] 4 | #![no_main] 5 | #![deny(unsafe_code)] 6 | 7 | use defmt_rtt as _; 8 | use panic_probe as _; 9 | 10 | use cortex_m::prelude::_embedded_hal_blocking_delay_DelayMs; 11 | use cortex_m_rt::entry; 12 | use stm32f1xx_hal::gpio::IOPinSpeed; 13 | use stm32f1xx_hal::gpio::OutputSpeed; 14 | use stm32f1xx_hal::pac; 15 | use stm32f1xx_hal::prelude::_fugit_ExtU32; 16 | use stm32f1xx_hal::prelude::_stm32_hal_flash_FlashExt; 17 | use stm32f1xx_hal::prelude::_stm32_hal_gpio_GpioExt; 18 | use stm32f1xx_hal::rcc::RccExt; 19 | use stm32f1xx_hal::timer::SysTimerExt; 20 | 21 | #[entry] 22 | fn main() -> ! { 23 | // 获取对外设的访问对象 24 | let cp = cortex_m::Peripherals::take().unwrap(); 25 | let dp = pac::Peripherals::take().unwrap(); 26 | 27 | // 获得原始flash和rcc设备的所有权,并将它们转换为相应的HAL结构 28 | let mut flash = dp.FLASH.constrain(); 29 | let rcc = dp.RCC.constrain(); 30 | 31 | // 冻结系统中所有时钟的配置,并将冻结的频率存储在时钟中 32 | let clocks = rcc.cfgr.freeze(&mut flash.acr); 33 | 34 | // 获取GPIO外围设备 35 | let mut gpioa = dp.GPIOA.split(); 36 | 37 | // 将 PA0 引脚配置为推挽式输出。 38 | let mut led = gpioa.pa0.into_push_pull_output(&mut gpioa.crl); 39 | // 设置其输出速度(50 MHz)。 40 | // 然后在接下来的代码中,我们将使用该引脚来控制 LED 的状态。 41 | led.set_speed(&mut gpioa.crl, IOPinSpeed::Mhz50); 42 | 43 | // 具有自定义精度的阻塞延迟 44 | let mut delay = cp.SYST.delay(&clocks); 45 | 46 | // 等待计时器触发更新并更改LED的状态 47 | loop { 48 | led.set_high(); 49 | // Use `embedded_hal::DelayMs` trait 50 | delay.delay_ms(1_000_u16); 51 | led.set_low(); 52 | // or use `fugit` duration units 53 | delay.delay(1.secs()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/general_gpio/dynamic_gpio/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dynamic_gpio" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | embedded-hal = "0.2.7" 12 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 13 | defmt = "0.3.5" 14 | defmt-rtt = "0.4.0" 15 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 16 | nb = "1" 17 | -------------------------------------------------------------------------------- /app/general_gpio/dynamic_gpio/README.md: -------------------------------------------------------------------------------- 1 | # 动态设置 GPIO 模式 2 | 3 | 这是一个动态设置 GPIO 模式的示例。在循环中动态设置 GPIO 引脚的模式。 4 | 5 | 该示例来自 hal 库的示例。 6 | 7 | ## 执行指令 8 | 9 | ```shell 10 | cargo rp dynamic_gpio 11 | ``` 12 | 13 | ## 学习目标 14 | 15 | - 动态设置 GPIO 模式 16 | 17 | ## 接线图 18 | 19 | ![](../../../images/wiring_diagram/3-1%20LED闪烁.jpg) 20 | -------------------------------------------------------------------------------- /app/general_gpio/dynamic_gpio/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use defmt::println; 5 | use defmt_rtt as _; 6 | use panic_probe as _; 7 | 8 | use cortex_m_rt::entry; 9 | use embedded_hal::digital::v2::InputPin; 10 | use embedded_hal::digital::v2::OutputPin; 11 | use nb::block; 12 | use stm32f1xx_hal::pac; 13 | use stm32f1xx_hal::prelude::_fugit_RateExtU32; 14 | use stm32f1xx_hal::prelude::_stm32_hal_flash_FlashExt; 15 | use stm32f1xx_hal::prelude::_stm32_hal_gpio_GpioExt; 16 | use stm32f1xx_hal::rcc::RccExt; 17 | use stm32f1xx_hal::timer::SysTimerExt; 18 | 19 | #[entry] 20 | fn main() -> ! { 21 | // Get access to the core peripherals from the cortex-m crate 22 | let cp = cortex_m::Peripherals::take().unwrap(); 23 | // Get access to the device specific peripherals from the peripheral access crate 24 | let dp = pac::Peripherals::take().unwrap(); 25 | 26 | // Take ownership over the raw flash and rcc devices and convert them into the corresponding 27 | // HAL structs 28 | let mut flash = dp.FLASH.constrain(); 29 | let rcc = dp.RCC.constrain(); 30 | 31 | // Freeze the configuration of all the clocks in the system and store the frozen frequencies in 32 | // `clocks` 33 | let clocks = rcc.cfgr.freeze(&mut flash.acr); 34 | 35 | // Acquire the GPIOA peripheral 36 | let mut gpioa = dp.GPIOA.split(); 37 | 38 | let mut pin = gpioa.pa0.into_dynamic(&mut gpioa.crl); 39 | // Configure the syst timer to trigger an update every second 40 | let mut timer = cp.SYST.counter_hz(&clocks); 41 | timer.start(1.Hz()).unwrap(); 42 | 43 | // Wait for the timer to trigger an update and change the state of the LED 44 | loop { 45 | pin.make_floating_input(&mut gpioa.crl); 46 | block!(timer.wait()).unwrap(); 47 | println!("{}", pin.is_high().unwrap()); 48 | 49 | pin.make_push_pull_output(&mut gpioa.crl); 50 | pin.set_high().unwrap(); 51 | block!(timer.wait()).unwrap(); 52 | pin.set_low().unwrap(); 53 | block!(timer.wait()).unwrap(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/general_gpio/ffi-blinky/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ffi-blinky" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.stm32f10x_rs] 17 | path = "../../../core/stm32f10x_rs" 18 | -------------------------------------------------------------------------------- /app/general_gpio/ffi-blinky/README.md: -------------------------------------------------------------------------------- 1 | # FFI 绑定版的闪烁 LED 2 | 3 | 这是一个 FFI 绑定版的闪烁 LED 的示例。 4 | 5 | 注意: 6 | 7 | - 这里成功点亮 LED, 但是没有闪烁。 8 | - 同时延时视乎存在异常。 9 | - 毫秒与微秒错位了。 10 | 11 | ## 执行指令 12 | 13 | ```shell 14 | cargo rp ffi-blinky 15 | 16 | cargo run --target thumbv7m-none-eabi -p ffi-blinky probe-run -- --chip STM32F103C8 trace 17 | ``` 18 | 19 | ## 逐步调制指令 20 | 21 | ```shell 22 | # 编译 23 | cargo build --target thumbv7m-none-eabi -p ffi-blinky 24 | 25 | # 烧录 26 | probe-run --chip STM32F103C8 target/thumbv7m-none-eabi/debug/ffi-blinky 27 | ``` 28 | 29 | ## 学习目标 30 | 31 | - 设置定时器 32 | - 设置高电平 33 | - 设置低电平 34 | 35 | ## 接线图 36 | 37 | ![](../../../images/wiring_diagram/3-1%20LED闪烁.jpg) 38 | -------------------------------------------------------------------------------- /app/general_gpio/key_control_led/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "key_control_led" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | -------------------------------------------------------------------------------- /app/general_gpio/key_control_led/README.md: -------------------------------------------------------------------------------- 1 | # 按键控制 LED 2 | 3 | 这是一个按键控制 LED 灯的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp key_control_led 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 配置按键 14 | - 配置 lED 灯 15 | 16 | ## 接线图 17 | 18 | ![](../../../images/wiring_diagram/3-4%20按键控制LED.jpg) 19 | -------------------------------------------------------------------------------- /app/general_gpio/led_flow_light/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "led_flow_light" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | -------------------------------------------------------------------------------- /app/general_gpio/led_flow_light/README.md: -------------------------------------------------------------------------------- 1 | # LED 流水灯 2 | 3 | 这是一个 LED 流水灯的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp led_flow_light 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 闪烁多个 LED 灯 14 | 15 | ## 接线图 16 | 17 | ![](../../../images/wiring_diagram/3-2%20LED流水灯.jpg) 18 | -------------------------------------------------------------------------------- /app/general_gpio/led_flow_light/src/main.rs: -------------------------------------------------------------------------------- 1 | //! Blinks several LEDs stored in an array 2 | 3 | #![no_std] 4 | #![no_main] 5 | #![deny(unsafe_code)] 6 | 7 | use defmt_rtt as _; 8 | use panic_probe as _; 9 | 10 | use cortex_m_rt::entry; 11 | use stm32f1xx_hal::pac; 12 | use stm32f1xx_hal::prelude::_fugit_ExtU32; 13 | use stm32f1xx_hal::prelude::_stm32_hal_flash_FlashExt; 14 | use stm32f1xx_hal::prelude::_stm32_hal_gpio_GpioExt; 15 | use stm32f1xx_hal::rcc::RccExt; 16 | use stm32f1xx_hal::timer::SysTimerExt; 17 | 18 | #[entry] 19 | fn main() -> ! { 20 | // 获取对外设的访问对象 21 | let cp = cortex_m::Peripherals::take().unwrap(); 22 | let dp = pac::Peripherals::take().unwrap(); 23 | 24 | // 获得原始flash和rcc设备的所有权,并将它们转换为相应的HAL结构 25 | let mut flash = dp.FLASH.constrain(); 26 | let rcc = dp.RCC.constrain(); 27 | 28 | // 冻结系统中所有时钟的配置,并将冻结的频率存储在时钟中 29 | let clocks = rcc.cfgr.freeze(&mut flash.acr); 30 | 31 | // 具有自定义精度的阻塞延迟 32 | let mut delay = cp.SYST.delay(&clocks); 33 | 34 | // 获取GPIO外围设备 35 | let mut gpioa = dp.GPIOA.split(); 36 | 37 | // 创建要闪烁的LED阵列 38 | let mut leds = [ 39 | gpioa.pa0.into_push_pull_output(&mut gpioa.crl).erase(), 40 | gpioa.pa1.into_push_pull_output(&mut gpioa.crl).erase(), 41 | gpioa.pa2.into_push_pull_output(&mut gpioa.crl).erase(), 42 | gpioa.pa3.into_push_pull_output(&mut gpioa.crl).erase(), 43 | gpioa.pa4.into_push_pull_output(&mut gpioa.crl).erase(), 44 | gpioa.pa5.into_push_pull_output(&mut gpioa.crl).erase(), 45 | gpioa.pa6.into_push_pull_output(&mut gpioa.crl).erase(), 46 | gpioa.pa7.into_push_pull_output(&mut gpioa.crl).erase(), 47 | ]; 48 | 49 | loop { 50 | for led in leds.iter_mut() { 51 | led.set_high(); 52 | delay.delay(500.millis()); 53 | led.set_low(); 54 | delay.delay(500.millis()); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/general_gpio/light_sensor_control_buzzer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "light_sensor_control_buzzer" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | -------------------------------------------------------------------------------- /app/general_gpio/light_sensor_control_buzzer/README.md: -------------------------------------------------------------------------------- 1 | # 光敏传感器控制蜂鸣器 2 | 3 | 这是一个光敏传感器控制蜂鸣器的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp light_sensor_control_buzzer 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 配置光敏传感器 14 | - 配置蜂鸣器 15 | 16 | ## 接线图 17 | 18 | ![](../../../images/wiring_diagram/3-5%20光敏传感器控制蜂鸣器.jpg) 19 | -------------------------------------------------------------------------------- /app/general_gpio/light_sensor_control_buzzer/src/main.rs: -------------------------------------------------------------------------------- 1 | //! 按键控制 LED 2 | 3 | #![no_std] 4 | #![no_main] 5 | #![deny(unsafe_code)] 6 | 7 | use defmt_rtt as _; 8 | use panic_probe as _; 9 | 10 | use cortex_m::prelude::_embedded_hal_blocking_delay_DelayMs; 11 | use cortex_m_rt::entry; 12 | use stm32f1xx_hal::gpio; 13 | use stm32f1xx_hal::gpio::IOPinSpeed; 14 | use stm32f1xx_hal::gpio::OutputSpeed; 15 | use stm32f1xx_hal::pac; 16 | use stm32f1xx_hal::prelude::_stm32_hal_flash_FlashExt; 17 | use stm32f1xx_hal::prelude::_stm32_hal_gpio_GpioExt; 18 | use stm32f1xx_hal::rcc::RccExt; 19 | use stm32f1xx_hal::timer::SysTimerExt; 20 | 21 | #[entry] 22 | fn main() -> ! { 23 | // 获取对外设的访问对象 24 | let cp: cortex_m::Peripherals = cortex_m::Peripherals::take().unwrap(); 25 | let dp: pac::Peripherals = pac::Peripherals::take().unwrap(); 26 | 27 | // 获得原始flash和rcc设备的所有权,并将它们转换为相应的HAL结构 28 | let mut flash = dp.FLASH.constrain(); 29 | let rcc = dp.RCC.constrain(); 30 | 31 | // 冻结系统中所有时钟的配置,并将冻结的频率存储在时钟中 32 | let clocks = rcc.cfgr.freeze(&mut flash.acr); 33 | 34 | // 具有自定义精度的阻塞延迟 35 | let mut delay = cp.SYST.delay(&clocks); 36 | 37 | let mut gpiob = dp.GPIOB.split(); 38 | 39 | // 上电延时 40 | delay.delay_ms(20u16); 41 | 42 | // 蜂鸣器 43 | // 将 pin 引脚配置为推挽式输出 44 | let mut buzzer = gpiob.pb12.into_push_pull_output(&mut gpiob.crh); 45 | // 设置其输出速度(50 MHz)。 46 | buzzer.set_speed(&mut gpiob.crh, IOPinSpeed::Mhz50); 47 | 48 | // 光敏传感器 49 | // 将 pin 引脚配置为上拉输入 50 | let light_sensor = gpiob.pb13.into_pull_up_input(&mut gpiob.crh); 51 | 52 | loop { 53 | if light_sensor.is_high() { 54 | buzzer_on(&mut buzzer); 55 | } else { 56 | buzzer_off(&mut buzzer); 57 | } 58 | // 检测间隔延时 59 | delay.delay_ms(200_u16); 60 | } 61 | } 62 | 63 | /// 打开蜂鸣器 64 | fn buzzer_on(buzzer: &mut gpio::Pin<'B', 12, gpio::Output>) { 65 | buzzer.set_high(); 66 | } 67 | 68 | /// 关闭蜂鸣器 69 | fn buzzer_off(buzzer: &mut gpio::Pin<'B', 12, gpio::Output>) { 70 | buzzer.set_low(); 71 | } 72 | -------------------------------------------------------------------------------- /app/general_gpio/multi_mode_gpio/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "multi_mode_gpio" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | nb = "1" 16 | -------------------------------------------------------------------------------- /app/general_gpio/multi_mode_gpio/README.md: -------------------------------------------------------------------------------- 1 | # 运行中更改 GPIO 模式 2 | 3 | 这是一个运行中更改 GPIO 模式的示例。在循环中动态调整 GPIO 引脚的模式。 4 | 5 | 该示例来自 hal 库的示例。 6 | 7 | ## 执行指令 8 | 9 | ```shell 10 | cargo rp multi_mode_gpio 11 | ``` 12 | 13 | ## 学习目标 14 | 15 | - 更改 GPIO 模式 16 | 17 | ## 接线图 18 | 19 | ![](../../../images/wiring_diagram/3-1%20LED闪烁.jpg) 20 | -------------------------------------------------------------------------------- /app/general_gpio/multi_mode_gpio/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use defmt::println; 5 | use defmt_rtt as _; 6 | use panic_probe as _; 7 | 8 | use cortex_m_rt::entry; 9 | use nb::block; 10 | use stm32f1xx_hal::gpio::PinState; 11 | use stm32f1xx_hal::pac; 12 | use stm32f1xx_hal::prelude::_fugit_RateExtU32; 13 | use stm32f1xx_hal::prelude::_stm32_hal_flash_FlashExt; 14 | use stm32f1xx_hal::prelude::_stm32_hal_gpio_GpioExt; 15 | use stm32f1xx_hal::rcc::RccExt; 16 | use stm32f1xx_hal::timer::Timer; 17 | 18 | #[entry] 19 | fn main() -> ! { 20 | // Get access to the core peripherals from the cortex-m crate 21 | let cp = cortex_m::Peripherals::take().unwrap(); 22 | // Get access to the device specific peripherals from the peripheral access crate 23 | let dp = pac::Peripherals::take().unwrap(); 24 | 25 | // Take ownership over the raw flash and rcc devices and convert them into the corresponding 26 | // HAL structs 27 | let mut flash = dp.FLASH.constrain(); 28 | let rcc = dp.RCC.constrain(); 29 | 30 | // Freeze the configuration of all the clocks in the system and store the frozen frequencies in 31 | // `clocks` 32 | let clocks = rcc.cfgr.freeze(&mut flash.acr); 33 | 34 | // Acquire the GPIOA peripheral 35 | let mut gpioa = dp.GPIOA.split(); 36 | 37 | let mut pin = gpioa.pa0.into_floating_input(&mut gpioa.crl); 38 | // Configure the syst timer to trigger an update every second 39 | let mut timer = Timer::syst(cp.SYST, &clocks).counter_hz(); 40 | timer.start(1.Hz()).unwrap(); 41 | 42 | // Wait for the timer to trigger an update and change the state of the LED 43 | loop { 44 | block!(timer.wait()).unwrap(); 45 | println!("{}", pin.is_high()); 46 | pin.as_push_pull_output(&mut gpioa.crl, |out| { 47 | out.set_high(); 48 | block!(timer.wait()).unwrap(); 49 | out.set_low(); 50 | block!(timer.wait()).unwrap(); 51 | }); 52 | pin.as_push_pull_output_with_state(&mut gpioa.crl, PinState::High, |out| { 53 | block!(timer.wait()).unwrap(); 54 | out.set_low(); 55 | block!(timer.wait()).unwrap(); 56 | }); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/general_gpio/tim2_timer_delay_blinky/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tim2_timer_delay_blinky" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | nb = "1" 16 | -------------------------------------------------------------------------------- /app/general_gpio/tim2_timer_delay_blinky/README.md: -------------------------------------------------------------------------------- 1 | # TIM2 通用定时器延迟闪烁 LED 2 | 3 | 使用 TIM2 通用定时器演示阻塞“延迟”的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp tim2_timer_delay_blinky 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 熟悉 TIM2 通用定时器的用法 14 | -------------------------------------------------------------------------------- /app/general_gpio/tim2_timer_delay_blinky/src/main.rs: -------------------------------------------------------------------------------- 1 | //! Demonstrate the use of a blocking `Delay` using TIM2 general-purpose timer. 2 | 3 | #![no_std] 4 | #![no_main] 5 | #![deny(unsafe_code)] 6 | 7 | use defmt_rtt as _; 8 | use panic_probe as _; 9 | 10 | use cortex_m::prelude::_embedded_hal_blocking_delay_DelayMs; 11 | use cortex_m_rt::entry; 12 | use stm32f1xx_hal::gpio::IOPinSpeed; 13 | use stm32f1xx_hal::gpio::OutputSpeed; 14 | use stm32f1xx_hal::pac; 15 | use stm32f1xx_hal::prelude::_fugit_ExtU32; 16 | use stm32f1xx_hal::prelude::_fugit_RateExtU32; 17 | use stm32f1xx_hal::prelude::_stm32_hal_flash_FlashExt; 18 | use stm32f1xx_hal::prelude::_stm32_hal_gpio_GpioExt; 19 | use stm32f1xx_hal::rcc::RccExt; 20 | use stm32f1xx_hal::timer::TimerExt; 21 | 22 | #[entry] 23 | fn main() -> ! { 24 | // 获取对外设的访问对象 25 | let _cp = cortex_m::Peripherals::take().unwrap(); 26 | let dp = pac::Peripherals::take().unwrap(); 27 | 28 | // 获得原始flash和rcc设备的所有权,并将它们转换为相应的HAL结构 29 | let mut flash = dp.FLASH.constrain(); 30 | let rcc = dp.RCC.constrain(); 31 | 32 | // 设置系统时钟。我们想在48MHz的频率下运行。 33 | let clocks = rcc 34 | .cfgr 35 | .use_hse(8.MHz()) 36 | .sysclk(48.MHz()) 37 | .freeze(&mut flash.acr); 38 | 39 | // 获取GPIO外围设备 40 | let mut gpioa = dp.GPIOA.split(); 41 | 42 | // 将 PA0 引脚配置为推挽式输出。 43 | let mut led = gpioa.pa0.into_push_pull_output(&mut gpioa.crl); 44 | // 设置其输出速度(50 MHz)。 45 | // 然后在接下来的代码中,我们将使用该引脚来控制 LED 的状态。 46 | led.set_speed(&mut gpioa.crl, IOPinSpeed::Mhz50); 47 | 48 | // 基于通用pupose 32位定时器TIM2创建延迟抽象 49 | 50 | //let mut delay = hal::timer::FTimerUs::new(dp.TIM2, &clocks).delay(); 51 | // or 52 | let mut delay = dp.TIM2.delay_us(&clocks); 53 | 54 | // 等待计时器触发更新并更改LED的状态 55 | loop { 56 | // On for 1s, off for 3s. 57 | led.set_high(); 58 | // Use `embedded_hal::DelayMs` trait 59 | delay.delay_ms(1000_u32); 60 | led.set_low(); 61 | // or use `fugit` duration units 62 | delay.delay(3.secs()); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/general_gpio/timer_blinky/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "timer_blinky" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | nb = "1" 16 | -------------------------------------------------------------------------------- /app/general_gpio/timer_blinky/README.md: -------------------------------------------------------------------------------- 1 | # 计时器闪烁 LED 2 | 3 | 这是一个使用计时器进行闪烁 LED 的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp timer_blinky 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 熟悉计时器的用法 14 | -------------------------------------------------------------------------------- /app/general_gpio/timer_blinky/src/main.rs: -------------------------------------------------------------------------------- 1 | //! "Blinky" using timer instead 2 | 3 | #![no_std] 4 | #![no_main] 5 | #![deny(unsafe_code)] 6 | 7 | use defmt_rtt as _; 8 | use panic_probe as _; 9 | 10 | use cortex_m_rt::entry; 11 | use nb::block; 12 | use stm32f1xx_hal::pac; 13 | use stm32f1xx_hal::prelude::_fugit_RateExtU32; 14 | use stm32f1xx_hal::prelude::_stm32_hal_flash_FlashExt; 15 | use stm32f1xx_hal::prelude::_stm32_hal_gpio_GpioExt; 16 | use stm32f1xx_hal::rcc::RccExt; 17 | use stm32f1xx_hal::timer::Timer; 18 | 19 | #[entry] 20 | fn main() -> ! { 21 | // 获取对外设的访问对象 22 | let cp = cortex_m::Peripherals::take().unwrap(); 23 | let dp = pac::Peripherals::take().unwrap(); 24 | 25 | // 获得原始flash和rcc设备的所有权,并将它们转换为相应的HAL结构 26 | let mut flash = dp.FLASH.constrain(); 27 | let rcc = dp.RCC.constrain(); 28 | 29 | // 冻结系统中所有时钟的配置,并将冻结的频率存储在时钟中 30 | let clocks = rcc.cfgr.freeze(&mut flash.acr); 31 | 32 | // 获取GPIO外围设备 33 | let mut gpioa = dp.GPIOA.split(); 34 | 35 | // 将系统计时器配置为每秒触发一次更新 36 | let mut timer = Timer::syst(cp.SYST, &clocks).counter_hz(); 37 | timer.start(1.Hz()).unwrap(); 38 | 39 | // 创建要闪烁的LED阵列 40 | let mut leds = [ 41 | gpioa.pa1.into_push_pull_output(&mut gpioa.crl).erase(), 42 | gpioa.pa2.into_push_pull_output(&mut gpioa.crl).erase(), 43 | ]; 44 | 45 | // 等待计时器触发更新并更改LED的状态 46 | loop { 47 | block!(timer.wait()).unwrap(); 48 | for led in leds.iter_mut() { 49 | led.set_high(); 50 | } 51 | block!(timer.wait()).unwrap(); 52 | for led in leds.iter_mut() { 53 | led.set_low(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/general_gpio/turns_user_led/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "turns_user_led" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | -------------------------------------------------------------------------------- /app/general_gpio/turns_user_led/README.md: -------------------------------------------------------------------------------- 1 | # 点灯 2 | 3 | 这是一个简单的点亮 LED 灯的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp turns_user_led 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 组装开发板 14 | - 点亮 LED 灯 15 | - 设置低电平 16 | 17 | ## 接线图 18 | 19 | ![](../../../images/wiring_diagram/2-1%20工程模板.jpg) 20 | ![](../../../images/wiring_diagram/3-1%20LED闪烁.jpg) 21 | -------------------------------------------------------------------------------- /app/general_gpio/turns_user_led/src/main.rs: -------------------------------------------------------------------------------- 1 | //! 点灯 2 | 3 | #![no_std] 4 | #![no_main] 5 | // 允许有空的循环结构; 6 | #![allow(clippy::empty_loop)] 7 | // 禁止使用 Rust 的 unsafe 代码; 8 | #![deny(unsafe_code)] 9 | 10 | // 用于处理错误情况; 11 | use defmt_rtt as _; 12 | use panic_probe as _; 13 | 14 | // 日志打印 15 | use defmt::println; 16 | // 用于标记程序入口; 17 | use cortex_m_rt::entry; 18 | // 可用于输出和相关AlternateMode引脚的回转速率 19 | use stm32f1xx_hal::gpio::IOPinSpeed; 20 | // 用于设置IO引脚的转换速率; 最初,所有引脚都设置为最大转换速率 21 | use stm32f1xx_hal::gpio::OutputSpeed; 22 | // 微控制器的外围访问API 23 | use stm32f1xx_hal::pac; 24 | // 在独立引脚和寄存器中拆分GPIO外设的扩展特性 25 | use stm32f1xx_hal::prelude::_stm32_hal_gpio_GpioExt; 26 | 27 | // 标记接下来的函数是程序的入口点; 28 | #[entry] 29 | fn main() -> ! { 30 | // 获取对特定设备外设的访问权限 31 | let p = pac::Peripherals::take().unwrap(); 32 | 33 | // 通过拆分 GPIOA 区块,获取对其各引脚的互斥访问。 34 | let mut gpioa = p.GPIOA.split(); 35 | 36 | // 将 PA0 引脚配置为推挽式输出。 37 | let mut led = gpioa.pa0.into_push_pull_output(&mut gpioa.crl); 38 | // 设置其输出速度(50 MHz)。 39 | // 然后在接下来的代码中,我们将使用该引脚来控制 LED 的状态。 40 | led.set_speed(&mut gpioa.crl, IOPinSpeed::Mhz50); 41 | 42 | println!("open led..."); 43 | // 设置低电平 44 | // led.set_low(); 45 | led.set_high(); 46 | 47 | // 无限循环 48 | loop {} 49 | } 50 | -------------------------------------------------------------------------------- /app/i2c/i2c_hard_mpu6050/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "i2c_hard_mpu6050" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = { version = "0.10.0", features = ["rt", "stm32f103", "medium"] } 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = { version = "0.3.1", features = ["print-defmt"] } 15 | embedded-dma = "0.2.0" 16 | nb = "1.1.0" 17 | unwrap-infallible = "0.1.5" 18 | heapless = "0.8.0" 19 | 20 | [dependencies.hardware] 21 | path = "../../../core/hardware" 22 | -------------------------------------------------------------------------------- /app/i2c/i2c_hard_mpu6050/README.md: -------------------------------------------------------------------------------- 1 | # I2C 硬件读写 MPU6050 2 | 3 | 这是一个使用 I2C 硬件读写 MPU6050 的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp i2c_hard_mpu6050 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解 I2C 通讯协议 14 | - 了解 MPU6050 6 轴姿态传感器 15 | - 了解硬件读写 MPU6050 16 | 17 | ## 接线图 18 | 19 | ![](../../../images/wiring_diagram/10-2%20硬件I2C读写MPU6050.jpg) 20 | -------------------------------------------------------------------------------- /app/i2c/i2c_mpu6050_crate/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "i2c_mpu6050_crate" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = { version = "0.10.0", features = ["rt", "stm32f103", "medium"] } 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = { version = "0.3.1", features = ["print-defmt"] } 15 | embedded-dma = "0.2.0" 16 | nb = "1.1.0" 17 | unwrap-infallible = "0.1.5" 18 | heapless = "0.8.0" 19 | # 6轴姿态传感器 20 | mpu6050 = "0.1.6" 21 | 22 | 23 | [dependencies.hardware] 24 | path = "../../../core/hardware" 25 | -------------------------------------------------------------------------------- /app/i2c/i2c_mpu6050_crate/README.md: -------------------------------------------------------------------------------- 1 | # I2C MPU6050 crate 读写 2 | 3 | 使用第三方 crate 进行读写 MPU6050。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp i2c_mpu6050_crate 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解 I2C 通讯协议 14 | - 了解 MPU6050 6 轴姿态传感器 15 | - 了解 MPU6050 crate 用法 16 | 17 | ## 接线图 18 | 19 | ![](../../../images/wiring_diagram/10-2%20硬件I2C读写MPU6050.jpg) 20 | -------------------------------------------------------------------------------- /app/i2c/i2c_oled_show_character/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "i2c_oled_show_character" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/i2c/i2c_oled_show_character/README.md: -------------------------------------------------------------------------------- 1 | # I2C OLED 通信协议显示字符 2 | 3 | 这是一个使用 I2C 通信协议在 OLED (有机发光二极管) 显示屏显示字符的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp i2c_oled_show_character 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解 OLED 显示屏 14 | - 4 脚 OLED 一般使用 I2C 15 | - 7 脚 OLED 一般使用 SPI 16 | - 分辨率:`128*64` 17 | - 配置 OLED 显示屏 18 | - 了解调试工具 19 | - 串口调试 20 | - 显示屏调试 21 | - GDB 调试 22 | - Keil 调试 23 | - 其他 24 | - 封装 OLED 字符发送函数 25 | 26 | ## 接线图 27 | 28 | ![](../../../images/wiring_diagram/4-1%20OLED显示屏.jpg) 29 | 30 | ## 相关文档 31 | 32 | - [OLED 屏幕字库的建立](https://blog.csdn.net/weixin_44597885/article/details/129233163) 33 | -------------------------------------------------------------------------------- /app/i2c/i2c_oled_show_character/src/main.rs: -------------------------------------------------------------------------------- 1 | //! OLED I2C 通信协议显示字符 2 | 3 | #![no_std] 4 | #![no_main] 5 | #![allow(clippy::empty_loop)] 6 | #![deny(unsafe_code)] 7 | 8 | use hardware::oled; 9 | 10 | use defmt::println; 11 | use defmt_rtt as _; 12 | use panic_probe as _; 13 | 14 | use cortex_m::prelude::_embedded_hal_blocking_delay_DelayMs; 15 | use cortex_m_rt::entry; 16 | use stm32f1xx_hal::flash::{self, FlashExt}; 17 | use stm32f1xx_hal::gpio::{gpiob, GpioExt}; 18 | use stm32f1xx_hal::pac; 19 | use stm32f1xx_hal::rcc::{self, RccExt}; 20 | use stm32f1xx_hal::timer::{SysDelay, SysTimerExt}; 21 | 22 | #[entry] 23 | fn main() -> ! { 24 | // 获取对外设的访问对象 25 | let cp = cortex_m::Peripherals::take().unwrap(); 26 | let dp = pac::Peripherals::take().unwrap(); 27 | let flash: flash::Parts = dp.FLASH.constrain(); 28 | let rcc: rcc::Rcc = dp.RCC.constrain(); 29 | let system_timer = cp.SYST; 30 | let mut gpiob: gpiob::Parts = dp.GPIOB.split(); 31 | 32 | // 封装具有自定义精度的阻塞延迟函数 33 | let mut delay = sys_delay(flash, rcc, system_timer); 34 | 35 | // 上电延时 36 | delay.delay_ms(20u16); 37 | 38 | // 初始化 OLED 显示屏 39 | println!("load oled..."); 40 | let mut oled = oled::simple::init_oled(gpiob.pb8, gpiob.pb9, &mut gpiob.crh); 41 | 42 | oled.show_char(1, 1, 'A'); 43 | oled.show_string(1, 3, "HelloWorld!"); 44 | oled.show_num(2, 1, 12345, 5); 45 | oled.show_signed_num(2, 7, -66, 2); 46 | oled.show_hex_num(3, 1, 0xAA55, 4); 47 | oled.show_bin_num(4, 1, 0xAA55, 16); 48 | 49 | loop {} 50 | } 51 | 52 | /// 封装具有自定义精度的阻塞延迟函数 53 | fn sys_delay( 54 | mut flash: flash::Parts, 55 | rcc: rcc::Rcc, 56 | system_timer: cortex_m::peripheral::SYST, 57 | ) -> SysDelay { 58 | // 冻结系统中所有时钟的配置,并将冻结的频率存储在时钟中 59 | let clocks = rcc.cfgr.freeze(&mut flash.acr); 60 | 61 | // 具有自定义精度的阻塞延迟 62 | system_timer.delay(&clocks) 63 | } 64 | -------------------------------------------------------------------------------- /app/i2c/i2c_soft_mpu6050/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "i2c_soft_mpu6050" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = { version = "0.10.0", features = ["rt", "stm32f103", "medium"] } 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = { version = "0.3.1", features = ["print-defmt"] } 15 | embedded-dma = "0.2.0" 16 | nb = "1.1.0" 17 | unwrap-infallible = "0.1.5" 18 | heapless = "0.8.0" 19 | 20 | [dependencies.hardware] 21 | path = "../../../core/hardware" 22 | -------------------------------------------------------------------------------- /app/i2c/i2c_soft_mpu6050/README.md: -------------------------------------------------------------------------------- 1 | # I2C 软件读写 MPU6050 2 | 3 | 这是一个使用 GPIO 模拟 I2C 读写 MPU6050 的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp i2c_soft_mpu6050 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解 I2C 通讯协议 14 | - 了解 MPU6050 6 轴姿态传感器 15 | - 了解软件读写 MPU6050 16 | 17 | ## 接线图 18 | 19 | ![](../../../images/wiring_diagram/10-1%20软件I2C读写MPU6050.jpg) 20 | -------------------------------------------------------------------------------- /app/interrupt/key_control_led_exti/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "key_control_led_exti" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | 17 | [dependencies.hardware] 18 | path = "../../../core/hardware" 19 | -------------------------------------------------------------------------------- /app/interrupt/key_control_led_exti/README.md: -------------------------------------------------------------------------------- 1 | # 按键中断电灯-EXTI 2 | 3 | 这是一个使用按键中断电灯-EXTI 的示例。按键触发时点亮 LED 灯,同时进行计数显示在 OLED 屏上。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp key_control_led_exti 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 按键/LED 接线 14 | - 中断配置 15 | - 注意:引脚与中断函数需要匹配 16 | 17 | ## 接线图 18 | 19 | ![](../../../images/wiring_diagram/3-4%20按键控制LED.jpg) 20 | -------------------------------------------------------------------------------- /app/interrupt/opposing_infrared_sensor_count/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "opposing_infrared_sensor_count" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/interrupt/opposing_infrared_sensor_count/README.md: -------------------------------------------------------------------------------- 1 | # 对射式红外传感器计次 2 | 3 | 这是一个使用对射式红外传感器计次的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp opposing_infrared_sensor_count 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解中断相关的知识点 14 | - 对射式红外传感器接线 15 | 16 | ## 接线图 17 | 18 | ![](../../../images/wiring_diagram/5-1%20对射式红外传感器计次.jpg) 19 | -------------------------------------------------------------------------------- /app/interrupt/opposing_infrared_sensor_count2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "opposing_infrared_sensor_count2" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/interrupt/opposing_infrared_sensor_count2/README.md: -------------------------------------------------------------------------------- 1 | # 对射式红外传感器计次 2 2 | 3 | 这是一个使用对射式红外传感器计次的示例, 该示例主要进行函数封装。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp opposing_infrared_sensor_count2 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解函数封装 14 | 15 | ## 接线图 16 | 17 | ![](../../../images/wiring_diagram/5-1%20对射式红外传感器计次.jpg) 18 | -------------------------------------------------------------------------------- /app/interrupt/rotary_encoder_count/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rotary_encoder_count" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/interrupt/rotary_encoder_count/README.md: -------------------------------------------------------------------------------- 1 | # 旋转编码器计次 2 | 3 | 这是一个使用旋转编码器次计次的示例。正向旋转输出正数,负向旋转输出负数。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp rotary_encoder_count 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解接入编码器 14 | - 若编码器与教程不一致, 可自行按引脚进行接入 15 | - 建议: 16 | - 在中断函数中最好不要执行耗时的代码,中断是处理突发事件的不适合耗时操作; 17 | - 不要在主程序和中断程序中操作可能产生冲突的硬件,可以用变量或标志位进行处理; 18 | 19 | ## 接线图 20 | 21 | ![](../../../images/wiring_diagram/5-2%20旋转编码器计次.jpg) 22 | -------------------------------------------------------------------------------- /app/interrupt/rtc_alarm_blinky_irq/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rtc_alarm_blinky_irq" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | nb = "1" 16 | 17 | [dependencies.hardware] 18 | path = "../../../core/hardware" 19 | -------------------------------------------------------------------------------- /app/interrupt/rtc_alarm_blinky_irq/README.md: -------------------------------------------------------------------------------- 1 | # RTC 告警中断闪烁 LED 2 | 3 | 这是一个使用 RTC 告警中断闪烁 LED 的示例。通过中断触发 LED 闪烁。 4 | 5 | 这里例子来自依赖库的官方案例。 6 | 7 | ## 执行指令 8 | 9 | ```shell 10 | cargo rp rtc_alarm_blinky_irq 11 | ``` 12 | 13 | ## 学习目标 14 | 15 | - 了解 RTC 中断 16 | -------------------------------------------------------------------------------- /app/interrupt/sys_timer_interrupt/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sys_timer_interrupt" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/interrupt/sys_timer_interrupt/README.md: -------------------------------------------------------------------------------- 1 | # 系统定时器中断 2 | 3 | 这是一个系统定时器中断的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp sys_timer_interrupt 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解系统定时器 14 | -------------------------------------------------------------------------------- /app/interrupt/timer_external_clock/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "timer_external_clock" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/interrupt/timer_external_clock/README.md: -------------------------------------------------------------------------------- 1 | # 定时器外部时钟 2 | 3 | 这是一个定时器外部时钟的示例。使用对射式红外传感器接入 PA0 引脚,PA0 引脚即 TIM2 的 ETR 引脚,引脚输入一个外部时钟。 4 | 5 | 预分频器的值和实际的分频系数相差 1,即实际分频系数=预分频器的值+1,这个预分频器的值是 16 位,所以最大值可以写 65535,也就是 65536 分频。预分频器就是对输入的基准频率提前进行一个分频的操作。 6 | 7 | 计数时钟每来一个上升沿,计数器的值就加 1,计数器是 16 位,所以里面的值可以从 0 一直加到 65535.如果再加的话,计数器就会回到 0 重新开始。所以计数器的值在计时过程中会不断自增运行,当自增运行到目标值时,产生中断,那就完成了定时的任务。 8 | 9 | 自动重装载寄存器:存储目标值的寄存器。在运行的过程中,计数值不断自增,自动重装值是固定的目标,当计数值等于自动重装值时,也就是计时时间到了。那他会产生一个中断信号,并且清零计数器。计数器自动开始下一次的计数计时。 10 | 11 | ## 执行指令 12 | 13 | ```shell 14 | cargo rp timer_external_clock 15 | ``` 16 | 17 | ## 学习目标 18 | 19 | - 了解定时器外部时钟 20 | 21 | ## 接线图 22 | 23 | ![](../../../images/wiring_diagram/6-2%20定时器外部时钟.jpg) 24 | -------------------------------------------------------------------------------- /app/interrupt/timer_interrupt_count_by_hz/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "timer_interrupt_count_by_hz" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/interrupt/timer_interrupt_count_by_hz/README.md: -------------------------------------------------------------------------------- 1 | # 定时器中断计数-赫兹 2 | 3 | 这是一个使用定时器中断计数的示例。使用指定赫兹触发定时器中断进行计数并在 OLED 中进行显示。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp timer_interrupt_count_by_hz 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解内部定时器 14 | - 了解中断系统 15 | 16 | ## 接线图 17 | 18 | ![](../../../images/wiring_diagram/6-1%20定时器定时中断.jpg) 19 | -------------------------------------------------------------------------------- /app/interrupt/timer_interrupt_count_by_seces/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "timer_interrupt_count_by_seces" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/interrupt/timer_interrupt_count_by_seces/README.md: -------------------------------------------------------------------------------- 1 | # 定时器中断计数-秒 2 | 3 | 这是一个使用定时器中断计数的示例。使用每秒触发一次定时器中断进行计数并在 OLED 中进行显示。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp timer_interrupt_count_by_seces 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解内部定时器 14 | - 了解中断系统 15 | 16 | ## 接线图 17 | 18 | ![](../../../images/wiring_diagram/6-1%20定时器定时中断.jpg) 19 | -------------------------------------------------------------------------------- /app/port_remap/disable_jtag_ports/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "disable_jtag_ports" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | -------------------------------------------------------------------------------- /app/port_remap/disable_jtag_ports/README.md: -------------------------------------------------------------------------------- 1 | # 禁用 JTAG 端口 2 | 3 | 这是一个禁用 JTAG 端口以访问 pb3、pb4 和 PA15 的示例。 4 | 5 | 这里例子来自依赖库的官方案例。 6 | 7 | ## 执行指令 8 | 9 | ```shell 10 | cargo rp disable_jtag_ports 11 | ``` 12 | 13 | ## 学习目标 14 | 15 | - 禁用 JTAG 端口 16 | -------------------------------------------------------------------------------- /app/port_remap/disable_jtag_ports/src/main.rs: -------------------------------------------------------------------------------- 1 | //! Disables the JTAG ports to give access to pb3, pb4 and PA15 2 | #![no_std] 3 | #![no_main] 4 | #![deny(unsafe_code)] 5 | 6 | use defmt_rtt as _; 7 | use panic_probe as _; 8 | 9 | use cortex_m_rt::entry; 10 | use stm32f1xx_hal::{pac, prelude::*}; 11 | 12 | #[entry] 13 | fn main() -> ! { 14 | let p = pac::Peripherals::take().unwrap(); 15 | 16 | let mut gpioa = p.GPIOA.split(); 17 | let mut gpiob = p.GPIOB.split(); 18 | let mut afio = p.AFIO.constrain(); 19 | 20 | let (pa15, pb3, pb4) = afio.mapr.disable_jtag(gpioa.pa15, gpiob.pb3, gpiob.pb4); 21 | 22 | let mut pa15 = pa15.into_push_pull_output(&mut gpioa.crh); 23 | let mut pb3 = pb3.into_push_pull_output(&mut gpiob.crl); 24 | let mut pb4 = pb4.into_push_pull_output(&mut gpiob.crl); 25 | 26 | loop { 27 | pa15.toggle(); 28 | pb3.toggle(); 29 | pb4.toggle(); 30 | cortex_m::asm::delay(8_000_000); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/pwm/pwm_custom/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pwm_custom" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/pwm/pwm_custom/README.md: -------------------------------------------------------------------------------- 1 | # 自定义引脚组合的 PWM 输出 2 | 3 | 这是一个使用自定义引脚组合的 PWM 输出的示例。 4 | 5 | 这里将介绍 Channel、断点、GDB 的综合使用。 6 | 7 | 同时了解 disable jtag 的用法。 8 | 9 | 这里例子来自依赖库的官方案例。 10 | 11 | ## 执行指令 12 | 13 | ```shell 14 | cargo rp pwm_custom 15 | ``` 16 | 17 | ## 学习目标 18 | 19 | - 了解 Channel 用法 20 | - 了解 bkpt 的用法 21 | - GDB 调试 22 | -------------------------------------------------------------------------------- /app/pwm/pwm_custom/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![allow(clippy::empty_loop)] 4 | 5 | use defmt::println; 6 | use defmt_rtt as _; 7 | use panic_probe as _; 8 | 9 | use cortex_m::asm; 10 | use cortex_m_rt::entry; 11 | use stm32f1xx_hal::pac; 12 | use stm32f1xx_hal::prelude::{ 13 | _fugit_RateExtU32, _stm32_hal_afio_AfioExt, _stm32_hal_flash_FlashExt, _stm32_hal_gpio_GpioExt, 14 | }; 15 | use stm32f1xx_hal::rcc::RccExt; 16 | use stm32f1xx_hal::timer::Timer; 17 | 18 | #[entry] 19 | fn main() -> ! { 20 | // 获取对外设的访问对象 21 | let _cp = cortex_m::Peripherals::take().unwrap(); 22 | let dp = pac::Peripherals::take().unwrap(); 23 | 24 | let mut flash = dp.FLASH.constrain(); 25 | let rcc = dp.RCC.constrain(); 26 | let mut afio = dp.AFIO.constrain(); 27 | let tim3: pac::TIM3 = dp.TIM3; 28 | 29 | let gpioa = dp.GPIOA.split(); 30 | let mut gpiob = dp.GPIOB.split(); 31 | 32 | // 冻结系统中所有时钟的配置,并将冻结的频率存储在时钟中 33 | let clocks = rcc 34 | .cfgr 35 | // .use_hse(8.MHz()) 36 | // 设置系统时钟 37 | // .sysclk(72.MHz()) 38 | // .pclk1(36.MHz()) 39 | .freeze(&mut flash.acr); 40 | 41 | let (_pa15, _pb3, pb4) = afio.mapr.disable_jtag(gpioa.pa15, gpiob.pb3, gpiob.pb4); 42 | 43 | // TIM3 44 | let p0 = pb4.into_alternate_push_pull(&mut gpiob.crl); 45 | let p1 = gpiob.pb5.into_alternate_push_pull(&mut gpiob.crl); 46 | let pins = (p0, p1); 47 | 48 | println!("load pwm..."); 49 | 50 | let pwm = Timer::new(tim3, &clocks).pwm_hz(pins, &mut afio.mapr, 1.kHz()); 51 | 52 | let max = pwm.get_max_duty(); 53 | 54 | let mut pwm_channels = pwm.split(); 55 | 56 | // Enable the individual channels 57 | pwm_channels.0.enable(); 58 | pwm_channels.1.enable(); 59 | 60 | // full 61 | pwm_channels.0.set_duty(max); 62 | pwm_channels.1.set_duty(max); 63 | 64 | asm::bkpt(); 65 | 66 | // dim 67 | pwm_channels.1.set_duty(max / 4); 68 | 69 | asm::bkpt(); 70 | 71 | // zero 72 | pwm_channels.0.set_duty(0); 73 | pwm_channels.1.set_duty(0); 74 | 75 | asm::bkpt(); 76 | 77 | loop {} 78 | } 79 | -------------------------------------------------------------------------------- /app/pwm/pwm_driven_motor/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pwm_driven_motor" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/pwm/pwm_driven_motor/README.md: -------------------------------------------------------------------------------- 1 | # PWM 驱动直流电机 2 | 3 | 这是一个使用 PWM 驱动直流电机的示例。 4 | 5 | 演示 PWM 控制直流电机速度以及正反转,按键控制电机速度,速度为 -100 到 100 之间的整数,负数表示反转,正数表示正转,绝对值越大速度越快。 6 | 7 | ## 执行指令 8 | 9 | ```shell 10 | cargo rp pwm_driven_motor 11 | ``` 12 | 13 | ## 学习目标 14 | 15 | - 电机驱动模块 TB6612FNG 引脚焊接 16 | - 电机驱动模块接线 17 | - 电机接线 18 | - 电机方向控制 19 | - 电机速度控制 20 | 21 | ## 接线图 22 | 23 | ![](../../../images/wiring_diagram/6-5%20PWM驱动直流电机.jpg) 24 | -------------------------------------------------------------------------------- /app/pwm/pwm_driven_servo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pwm_driven_servo" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/pwm/pwm_driven_servo/README.md: -------------------------------------------------------------------------------- 1 | # PWM 驱动舵机 2 | 3 | 这是一个使用 PWM 驱动舵机的示例。主要展示控制舵机旋转角度,以及旋转角度计算。 4 | 5 | 舵机的控制一般需要一个 20Ms 左右的时基脉冲,该脉冲的高电平部分一般为 0.5Ms~2.5Ms 范围内的角度控制脉冲部分,总间隔为 2Ms。 6 | 7 | 以 180° 舵机为例,对应的控制关系如下: 8 | 9 | - 53333.0 20ms 10 | - 1333.3 0.5ms -90 度 11 | - 3999.9 1.5ms 0 度 12 | - 5333.3 2ms 45 度 13 | - 6666.6 2.5ms 90 度 14 | - 缩放 = (6666.6-5333.3)/(90-45) = 29.6 15 | - duty = angle \* 29.6 + 1333.3 16 | 17 | ## 执行指令 18 | 19 | ```shell 20 | cargo rp pwm_driven_servo 21 | ``` 22 | 23 | ## 学习目标 24 | 25 | - 了解舵机基础信息 26 | - 舵机接线 27 | - 计算旋转角度 28 | 29 | ## 接线图 30 | 31 | ![](../../../images/wiring_diagram/6-4%20PWM驱动舵机.jpg) 32 | -------------------------------------------------------------------------------- /app/pwm/pwm_input_capture_freq_duty_cycle/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pwm_input_capture_freq_duty_cycle" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/pwm/pwm_input_capture_freq_duty_cycle/README.md: -------------------------------------------------------------------------------- 1 | # PWM 输入捕获模式测频率占空比 2 | 3 | 这是一个使用 pwm_input 实现输入捕获模式测频率的示例。演示测量自己 PWM 模块生产波形的频率及占空比。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp pwm_input_capture_freq_duty_cycle 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解输入捕获模式 14 | - 了解频率 15 | - 了解占空比 16 | 17 | ## 接线图 18 | 19 | ![](../../../images/wiring_diagram/6-7%20PWMI模式测频率占空比.jpg) 20 | -------------------------------------------------------------------------------- /app/pwm/pwm_led/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pwm_led" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/pwm/pwm_led/README.md: -------------------------------------------------------------------------------- 1 | # PWM 驱动呼吸灯 2 | 3 | 这是一个使用 PWM 驱动呼吸灯的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp pwm_led 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解 WPM 原理 14 | 15 | ## 接线图 16 | 17 | ![](../../../images/wiring_diagram/6-3%20PWM驱动LED呼吸灯.jpg) 18 | -------------------------------------------------------------------------------- /app/pwm/pwm_led2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pwm_led2" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/pwm/pwm_led2/README.md: -------------------------------------------------------------------------------- 1 | # PWM 驱动呼吸灯 2 2 | 3 | 这是一个使用 PWM 驱动多个呼吸灯的示例。这里将介绍 Channel、断点、GDB 的综合使用。 4 | 5 | 这里例子来自依赖库的官方案例; 6 | 7 | ## 执行指令 8 | 9 | ```shell 10 | cargo rp pwm_led2 11 | ``` 12 | 13 | ## 学习目标 14 | 15 | - 了解 Channel 用法 16 | - 了解 bkpt 的用法 17 | - 结合 GDB 进行电灯 18 | 19 | ## 接线图 20 | 21 | ![](../../../images/wiring_diagram/6-3%20PWM驱动LED呼吸灯.jpg) 22 | -------------------------------------------------------------------------------- /app/pwm/pwm_led_remap/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pwm_led_remap" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/pwm/pwm_led_remap/README.md: -------------------------------------------------------------------------------- 1 | # PWM 驱动呼吸灯-端口重映射 2 | 3 | 这是一个使用 PWM 驱动多个呼吸灯的示例。这里将介绍 Channel、断点、GDB 的综合使用。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp pwm_led_remap 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解端口重映射方式 14 | - PA0 -> PA15, 同时注意进行调试功能 15 | 16 | ## 接线图 17 | 18 | ![](../../../images/wiring_diagram/6-3%20PWM驱动LED呼吸灯.jpg) 19 | -------------------------------------------------------------------------------- /app/pwm/pwm_rotary_encoder_count/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pwm_rotary_encoder_count" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/pwm/pwm_rotary_encoder_count/README.md: -------------------------------------------------------------------------------- 1 | # PWM 旋转编码器接口计数 2 | 3 | 这是一个使用 qei 实现旋转编码器接口计数的示例。演示测量旋转编码器下旋转计数。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp pwm_rotary_encoder_count 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解输入捕获模式 14 | 15 | ## 接线图 16 | 17 | ![](../../../images/wiring_diagram/6-8%20编码器接口测速.jpg) 18 | -------------------------------------------------------------------------------- /app/pwm/pwm_rotary_encoder_speed/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pwm_rotary_encoder_speed" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/pwm/pwm_rotary_encoder_speed/README.md: -------------------------------------------------------------------------------- 1 | # PWM 旋转编码器接口延时测速 2 | 3 | 这是一个使用 qei 实现旋转编码器接口测速的示例。演示使用延时测量旋转编码器下旋转速度。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp pwm_rotary_encoder_speed 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解输入捕获模式 14 | 15 | ## 接线图 16 | 17 | ![](../../../images/wiring_diagram/6-8%20编码器接口测速.jpg) 18 | -------------------------------------------------------------------------------- /app/pwm/pwm_rotary_encoder_timer_speed/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pwm_rotary_encoder_timer_speed" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/pwm/pwm_rotary_encoder_timer_speed/README.md: -------------------------------------------------------------------------------- 1 | # PWM 旋转编码器接口定时器测速 2 | 3 | 这是一个使用 qei 实现旋转编码器接口定时器测速的示例。演示使用定时器测量旋转编码器下旋转速度。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp pwm_rotary_encoder_timer_speed 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解输入捕获模式 14 | 15 | ## 接线图 16 | 17 | ![](../../../images/wiring_diagram/6-8%20编码器接口测速.jpg) 18 | -------------------------------------------------------------------------------- /app/pwr/sleep_mode_serial_tx_and_rx/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sleep_mode_serial_tx_and_rx" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | embedded-dma = "0.2.0" 16 | nb = "1.1.0" 17 | unwrap-infallible = "0.1.5" 18 | 19 | 20 | [dependencies.hardware] 21 | path = "../../../core/hardware" 22 | -------------------------------------------------------------------------------- /app/pwr/sleep_mode_serial_tx_and_rx/README.md: -------------------------------------------------------------------------------- 1 | # 睡眠模式-串口发送接收 2 | 3 | 这是一个睡眠模式下串口发送接收的示例。当接收到串口数据时唤醒程序,其他时间段处于睡眠状态。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp sleep_mode_serial_tx_and_rx 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解睡眠模式 14 | 15 | ## 接线图 16 | 17 | ![](../../../images/wiring_diagram/13-2%20睡眠模式+串口发送+接收.jpg) 18 | -------------------------------------------------------------------------------- /app/pwr/standby_mode_rtc_counter/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "standby_mode_rtc_counter" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | nb = "1" 16 | 17 | [dependencies.hardware] 18 | path = "../../../core/hardware" 19 | -------------------------------------------------------------------------------- /app/pwr/standby_mode_rtc_counter/README.md: -------------------------------------------------------------------------------- 1 | # 待机模式-实时时钟计数 2 | 3 | 使用待机模式下进行实时时钟计数的示例。主要演示待机模式下省电。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp standby_mode_rtc_counter 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解实时时钟 14 | - 待机模式 15 | 16 | ## 接线图 17 | 18 | ![](../../../images/wiring_diagram/13-4%20待机模式+实时时钟.jpg) 19 | -------------------------------------------------------------------------------- /app/pwr/stop_mode_infrared_sensor_count/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stop_mode_infrared_sensor_count" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | [dependencies.hardware] 17 | path = "../../../core/hardware" 18 | -------------------------------------------------------------------------------- /app/pwr/stop_mode_infrared_sensor_count/README.md: -------------------------------------------------------------------------------- 1 | # 停止模式-对射式红外传感器计次 2 | 3 | 这是一个使用停止模式下对射式红外传感器计次的示例,。演示停止模式下进行省电的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp stop_mode_infrared_sensor_count 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解停止模式 14 | 15 | ## 接线图 16 | 17 | ![](../../../images/wiring_diagram/13-3%20停止模式+对射式红外传感器计次.jpg) 18 | -------------------------------------------------------------------------------- /app/pwr/syst_freq/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "syst_freq" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | 17 | [dependencies.hardware] 18 | path = "../../../core/hardware" 19 | -------------------------------------------------------------------------------- /app/pwr/syst_freq/README.md: -------------------------------------------------------------------------------- 1 | # 修改系统时钟主频 2 | 3 | 这是一个修改系统时钟主频的示例。通过降低主频达到省电的目的。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp syst_freq 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解系统时钟 14 | - 修改系统时钟主频 15 | 16 | ## 接线图 17 | 18 | ![](../../../images/wiring_diagram/13-1%20修改主频.jpg) 19 | -------------------------------------------------------------------------------- /app/pwr/syst_freq/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![allow(clippy::empty_loop)] 4 | 5 | use hardware::oled; 6 | 7 | use defmt::println; 8 | use defmt_rtt as _; 9 | use panic_probe as _; 10 | 11 | use cortex_m_rt::entry; 12 | use stm32f1xx_hal::pac; 13 | use stm32f1xx_hal::prelude::_embedded_hal_blocking_delay_DelayMs; 14 | use stm32f1xx_hal::prelude::_fugit_RateExtU32; 15 | use stm32f1xx_hal::prelude::_stm32_hal_flash_FlashExt; 16 | use stm32f1xx_hal::prelude::_stm32_hal_gpio_GpioExt; 17 | use stm32f1xx_hal::rcc::RccExt; 18 | use stm32f1xx_hal::timer::SysTimerExt; 19 | 20 | #[entry] 21 | fn main() -> ! { 22 | // 获取对外设的访问对象 23 | let cp = cortex_m::Peripherals::take().unwrap(); 24 | let dp = pac::Peripherals::take().unwrap(); 25 | 26 | let mut flash = dp.FLASH.constrain(); 27 | let rcc = dp.RCC.constrain(); 28 | let syst = cp.SYST; 29 | 30 | let mut gpiob = dp.GPIOB.split(); 31 | 32 | // 冻结系统中所有时钟的配置,并将冻结的频率存储在时钟中 33 | let clocks = rcc 34 | .cfgr 35 | // 设置SYSCLK时钟所需的频率 36 | .sysclk(72.MHz()) 37 | // .sysclk(36.MHz()) 38 | .freeze(&mut flash.acr); 39 | 40 | // 具有自定义精度的阻塞延迟函数 41 | let mut delay = syst.delay(&clocks); 42 | 43 | // 初始化 OLED 显示屏 44 | println!("load oled..."); 45 | let mut oled = oled::simple::init_oled(gpiob.pb8, gpiob.pb9, &mut gpiob.crh); 46 | 47 | oled.show_string(1, 1, "SYSCLK:"); 48 | oled.show_num(1, 8, clocks.sysclk().to_Hz(), 8); 49 | loop { 50 | oled.show_string(2, 1, "running"); 51 | delay.delay_ms(500_u32); 52 | oled.show_string(2, 1, " "); 53 | delay.delay_ms(500_u32); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/rtc/rtc_alarm_blinky/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rtc_alarm_blinky" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | nb = "1" 16 | 17 | [dependencies.hardware] 18 | path = "../../../core/hardware" 19 | -------------------------------------------------------------------------------- /app/rtc/rtc_alarm_blinky/README.md: -------------------------------------------------------------------------------- 1 | # RTC 告警闪烁 LED 2 | 3 | 这是一个使用 RTC 告警闪烁 LED 的示例。每在 5 秒内触发一次 LED 闪烁。 4 | 5 | 这里例子来自依赖库的官方案例。 6 | 7 | ## 执行指令 8 | 9 | ```shell 10 | cargo rp rtc_blinky 11 | ``` 12 | 13 | ## 学习目标 14 | 15 | - 了解 RTC 16 | -------------------------------------------------------------------------------- /app/rtc/rtc_alarm_blinky/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![allow(clippy::empty_loop)] 4 | 5 | use defmt::println; 6 | use defmt_rtt as _; 7 | use panic_probe as _; 8 | 9 | use cortex_m_rt::entry; 10 | use nb::block; 11 | use stm32f1xx_hal::pac; 12 | use stm32f1xx_hal::prelude::_stm32_hal_flash_FlashExt; 13 | use stm32f1xx_hal::prelude::_stm32_hal_gpio_GpioExt; 14 | use stm32f1xx_hal::rcc::RccExt; 15 | use stm32f1xx_hal::rtc::Rtc; 16 | use stm32f1xx_hal::timer::SysTimerExt; 17 | 18 | #[entry] 19 | fn main() -> ! { 20 | // 获取对外设的访问对象 21 | let cp = cortex_m::Peripherals::take().unwrap(); 22 | let dp = pac::Peripherals::take().unwrap(); 23 | 24 | let mut flash = dp.FLASH.constrain(); 25 | let rcc = dp.RCC.constrain(); 26 | let syst = cp.SYST; 27 | let mut pwr = dp.PWR; 28 | 29 | let mut gpioa = dp.GPIOA.split(); 30 | 31 | // 冻结系统中所有时钟的配置,并将冻结的频率存储在时钟中 32 | let clocks = rcc.cfgr.freeze(&mut flash.acr); 33 | 34 | // 具有自定义精度的阻塞延迟函数 35 | let mut _delay = syst.delay(&clocks); 36 | 37 | // 初始化 LED 38 | let mut led = gpioa.pa0.into_push_pull_output(&mut gpioa.crl); 39 | 40 | // 设置RTC 41 | // 启用对备份域的写入 42 | let mut backup_domain = rcc.bkp.constrain(dp.BKP, &mut pwr); 43 | // 启动RTC 44 | let mut rtc = Rtc::new(dp.RTC, &mut backup_domain); 45 | 46 | let mut led_on = false; 47 | 48 | println!("loop"); 49 | loop { 50 | // 将当前时间设置为0 51 | rtc.set_time(0); 52 | // 在 5 秒内触发 LED 闪烁 53 | rtc.set_alarm(5); 54 | block!(rtc.wait_alarm()).unwrap(); 55 | if led_on { 56 | led.set_low(); 57 | led_on = false; 58 | } else { 59 | led.set_high(); 60 | led_on = true; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/rtc/rtc_bkp/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rtc_bkp" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | 17 | [dependencies.hardware] 18 | path = "../../../core/hardware" 19 | -------------------------------------------------------------------------------- /app/rtc/rtc_bkp/README.md: -------------------------------------------------------------------------------- 1 | # BKP 断电恢复 2 | 3 | 这是一个使用备用电池供电,主电源断电后 BKP 恢复数据的示例。 4 | 5 | 演示主电源掉电后再上电显示的依旧是掉电前最后一次写入的数据。 6 | 7 | ## 执行指令 8 | 9 | ```shell 10 | cargo rp rtc_bkp 11 | ``` 12 | 13 | ## 学习目标 14 | 15 | - 了解 BKP 16 | 17 | ## 接线图 18 | 19 | ![](../../../images/wiring_diagram/12-2%20读写备份寄存器.jpg) 20 | -------------------------------------------------------------------------------- /app/rtc/rtc_bkp/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![allow(clippy::empty_loop)] 4 | 5 | use hardware::oled; 6 | 7 | use defmt::println; 8 | use defmt_rtt as _; 9 | use panic_probe as _; 10 | 11 | use cortex_m::asm::wfi; 12 | use cortex_m_rt::entry; 13 | use stm32f1xx_hal::pac; 14 | use stm32f1xx_hal::prelude::_stm32_hal_flash_FlashExt; 15 | use stm32f1xx_hal::prelude::_stm32_hal_gpio_GpioExt; 16 | use stm32f1xx_hal::rcc::RccExt; 17 | use stm32f1xx_hal::rtc::Rtc; 18 | use stm32f1xx_hal::timer::SysTimerExt; 19 | 20 | #[entry] 21 | fn main() -> ! { 22 | // 获取对外设的访问对象 23 | let cp = cortex_m::Peripherals::take().unwrap(); 24 | let dp = pac::Peripherals::take().unwrap(); 25 | 26 | let mut flash = dp.FLASH.constrain(); 27 | let rcc = dp.RCC.constrain(); 28 | let syst = cp.SYST; 29 | let mut pwr = dp.PWR; 30 | 31 | let mut gpiob = dp.GPIOB.split(); 32 | 33 | // 冻结系统中所有时钟的配置,并将冻结的频率存储在时钟中 34 | let clocks = rcc.cfgr.freeze(&mut flash.acr); 35 | 36 | // 具有自定义精度的阻塞延迟函数 37 | let mut _delay = syst.delay(&clocks); 38 | 39 | // 初始化 OLED 显示屏 40 | println!("load oled..."); 41 | let mut oled = oled::simple::init_oled(gpiob.pb8, gpiob.pb9, &mut gpiob.crh); 42 | 43 | // 设置RTC 44 | // 启用对备份域的写入 45 | let mut backup_domain = rcc.bkp.constrain(dp.BKP, &mut pwr); 46 | 47 | // 从备份数据寄存器的DR1至DR10寄存器之一读取16位值。 48 | // 寄存器自变量是DRx寄存器的一个从零开始的索引:0表示DR1,最多9表示DR10。 49 | // 提供9以上的数字会引起恐慌 50 | let dr1 = backup_domain.read_data_register_low(0); 51 | if dr1 == 0 { 52 | // 将16位值写入备份数据寄存器的DR1至DR10寄存器之一。 53 | // 寄存器自变量是DRx寄存器的一个从零开始的索引:0表示DR1,最多9表示DR10。 54 | // 提供高于9的数字会引起恐慌。 55 | backup_domain.write_data_register_low(0, 10); 56 | backup_domain.write_data_register_low(1, 20); 57 | } 58 | 59 | // 启动RTC 60 | let mut rtc = Rtc::new(dp.RTC, &mut backup_domain); 61 | 62 | // 将当前时间设置为0 63 | rtc.set_time(0); 64 | 65 | oled.show_string(1, 1, "R1:"); 66 | oled.show_string(2, 1, "R2:"); 67 | 68 | let dr1 = backup_domain.read_data_register_low(0); 69 | let dr2 = backup_domain.read_data_register_low(1); 70 | 71 | oled.show_num(1, 4, dr1 as u32, 5); 72 | oled.show_num(2, 4, dr2 as u32, 5); 73 | 74 | loop { 75 | wfi(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/rtc/rtc_bkp_dyn_data/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rtc_bkp_dyn_data" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | 17 | [dependencies.hardware] 18 | path = "../../../core/hardware" 19 | -------------------------------------------------------------------------------- /app/rtc/rtc_bkp_dyn_data/README.md: -------------------------------------------------------------------------------- 1 | # 读写备份寄存器 2 | 3 | 这是一个使用备用电池供电,主电源断电后 BKP 恢复动态数据的示例。 4 | 5 | 使用按键更新备份数据。 6 | 演示主电源掉电后再上电显示的依旧是掉电前最后一次写入的数据。 7 | 8 | ## 执行指令 9 | 10 | ```shell 11 | cargo rp rtc_bkp_dyn_data 12 | ``` 13 | 14 | ## 学习目标 15 | 16 | - 了解 BKP 17 | 18 | ## 接线图 19 | 20 | ![](../../../images/wiring_diagram/12-2%20读写备份寄存器.jpg) 21 | -------------------------------------------------------------------------------- /app/rtc/rtc_counter/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rtc_counter" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | 17 | [dependencies.hardware] 18 | path = "../../../core/hardware" 19 | -------------------------------------------------------------------------------- /app/rtc/rtc_counter/README.md: -------------------------------------------------------------------------------- 1 | # RTC 实时时钟计数器 2 | 3 | 使用实时时钟将当前时间(以秒为单位)输出到控制台。 4 | 5 | 这里例子来自依赖库的官方案例。 6 | 7 | ## 执行指令 8 | 9 | ```shell 10 | cargo rp rtc_counter 11 | ``` 12 | 13 | ## 学习目标 14 | 15 | - 了解 BKP 16 | - 了解实时时钟 17 | -------------------------------------------------------------------------------- /app/rtc/rtc_counter/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![allow(clippy::empty_loop)] 4 | 5 | use hardware::oled; 6 | 7 | use defmt::println; 8 | use defmt_rtt as _; 9 | use panic_probe as _; 10 | 11 | use cortex_m_rt::entry; 12 | use stm32f1xx_hal::pac; 13 | use stm32f1xx_hal::prelude::_embedded_hal_blocking_delay_DelayMs; 14 | use stm32f1xx_hal::prelude::_stm32_hal_flash_FlashExt; 15 | use stm32f1xx_hal::prelude::_stm32_hal_gpio_GpioExt; 16 | use stm32f1xx_hal::rcc::RccExt; 17 | use stm32f1xx_hal::rtc::Rtc; 18 | use stm32f1xx_hal::timer::SysTimerExt; 19 | 20 | #[entry] 21 | fn main() -> ! { 22 | // 获取对外设的访问对象 23 | let cp = cortex_m::Peripherals::take().unwrap(); 24 | let dp = pac::Peripherals::take().unwrap(); 25 | 26 | let mut flash = dp.FLASH.constrain(); 27 | let rcc = dp.RCC.constrain(); 28 | let syst = cp.SYST; 29 | let mut pwr = dp.PWR; 30 | 31 | let mut gpiob = dp.GPIOB.split(); 32 | 33 | // 冻结系统中所有时钟的配置,并将冻结的频率存储在时钟中 34 | let clocks = rcc.cfgr.freeze(&mut flash.acr); 35 | 36 | // 具有自定义精度的阻塞延迟函数 37 | let mut delay = syst.delay(&clocks); 38 | 39 | // 初始化 OLED 显示屏 40 | println!("load oled..."); 41 | let mut oled = oled::simple::init_oled(gpiob.pb8, gpiob.pb9, &mut gpiob.crh); 42 | 43 | // 设置RTC 44 | // 启用对备份域的写入 45 | let mut backup_domain = rcc.bkp.constrain(dp.BKP, &mut pwr); 46 | // 启动RTC 47 | let mut rtc = Rtc::new(dp.RTC, &mut backup_domain); 48 | 49 | // 将当前时间设置为0 50 | rtc.set_time(0); 51 | 52 | oled.show_string(1, 1, "time:"); 53 | loop { 54 | let time = rtc.current_time(); 55 | println!("time: {}", time); 56 | oled.show_num(1, 6, time, 5); 57 | delay.delay_ms(1000_u32); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/rtc/rtc_time/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rtc_time" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | time = {version = "0.3.28", default-features = false, features = [ 16 | "parsing", 17 | "macros", 18 | ]} 19 | 20 | [dependencies.hardware] 21 | path = "../../../core/hardware" 22 | -------------------------------------------------------------------------------- /app/rtc/rtc_time/README.md: -------------------------------------------------------------------------------- 1 | # RTC 实时时间 2 | 3 | 这是一个使用 RTC 实现实时时间的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp rtc_time 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解 BKP 14 | - 了解实时时钟 15 | - 了解时间处理 crate 16 | -------------------------------------------------------------------------------- /app/rtic/exti_rtic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "exti_rtic" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | embedded-hal = "0.2.7" 12 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 13 | rtic = { version = "2.0.1", features = [ "thumbv7-backend" ] } 14 | defmt = "0.3.5" 15 | defmt-rtt = "0.4.0" 16 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 17 | -------------------------------------------------------------------------------- /app/rtic/exti_rtic/README.md: -------------------------------------------------------------------------------- 1 | # EXTI 中断-RTIC 2 | 3 | 这是一个 EXTI 中断的 RTIC 实现的示例。 4 | 5 | 该示例来自 hal 库的示例。 6 | 7 | ## 执行指令 8 | 9 | ```shell 10 | cargo rp exti_rtic 11 | ``` 12 | 13 | ## 学习目标 14 | 15 | - 了解 EXTI 16 | - 了解 RTIC 17 | 18 | ## 接线图 19 | 20 | ![](../../../images/wiring_diagram/3-1%20LED闪烁.jpg) 21 | -------------------------------------------------------------------------------- /app/rtic/spawn_task_rtic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "spawn_task_rtic" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | embedded-hal = "0.2.7" 12 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 13 | rtic = {version = "2.0.1", features = ["thumbv7-backend"]} 14 | rtic-monotonics = {version = "1.2.0", features = ["cortex-m-systick"]} 15 | defmt = "0.3.5" 16 | defmt-rtt = "0.4.0" 17 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 18 | -------------------------------------------------------------------------------- /app/rtic/spawn_task_rtic/README.md: -------------------------------------------------------------------------------- 1 | # 任务调度-RTIC 2 | 3 | 这是一个任务调度的 RTIC 实现的示例。 4 | 5 | 该示例来自 hal 库的示例。 6 | 7 | ## 执行指令 8 | 9 | 注意:要求 `nightly` 版本 10 | 11 | ```shell 12 | cargo rp spawn_task_rtic 13 | ``` 14 | 15 | ## 学习目标 16 | 17 | - 了解 spawn 18 | - 了解 RTIC 19 | 20 | ## 接线图 21 | 22 | ![](../../../images/wiring_diagram/3-1%20LED闪烁.jpg) 23 | -------------------------------------------------------------------------------- /app/rtic/spawn_task_rtic/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![deny(unsafe_code)] 4 | #![deny(warnings)] 5 | #![feature(type_alias_impl_trait)] 6 | 7 | use defmt::println; 8 | use defmt_rtt as _; 9 | use panic_probe as _; 10 | 11 | use rtic_monotonics::systick::Systick; 12 | use stm32f1xx_hal::afio::AfioExt; 13 | use stm32f1xx_hal::flash::FlashExt; 14 | use stm32f1xx_hal::gpio; 15 | use stm32f1xx_hal::gpio::ExtiPin; 16 | use stm32f1xx_hal::prelude::_stm32_hal_gpio_GpioExt; 17 | use stm32f1xx_hal::prelude::_stm32_hal_rcc_RccExt; 18 | use stm32f1xx_hal::timer::SysDelay; 19 | use stm32f1xx_hal::timer::SysTimerExt; 20 | 21 | #[rtic::app(device = stm32f1xx_hal::pac, peripherals = true, dispatchers = [SPI1])] 22 | mod app { 23 | use super::*; 24 | 25 | #[shared] 26 | struct Shared {} 27 | 28 | #[local] 29 | struct Local { 30 | led: gpio::PA0>, 31 | state: bool, 32 | } 33 | 34 | #[init] 35 | fn init(mut ctx: init::Context) -> (Shared, Local) { 36 | let mut afio = ctx.device.AFIO.constrain(); 37 | let mut flash = ctx.device.FLASH.constrain(); 38 | let rcc = ctx.device.RCC.constrain(); 39 | let syst = ctx.core.SYST; 40 | 41 | // 初始化时钟 42 | let clocks = rcc.cfgr.freeze(&mut flash.acr); 43 | 44 | // 具有自定义精度的阻塞延迟 45 | let delay = syst.delay(&clocks); 46 | 47 | // LED 48 | let mut gpioa = ctx.device.GPIOA.split(); 49 | let led = gpioa.pa0.into_push_pull_output(&mut gpioa.crl); 50 | 51 | // Schedule the blinking task 52 | button_click::spawn().ok(); 53 | 54 | // 初始化静态资源以稍后通过RTIC使用它们 55 | (Shared {}, Local { led, state: false }) 56 | } 57 | 58 | #[task(local = [state, led])] 59 | async fn button_click(ctx: button_click::Context) { 60 | loop { 61 | println!("blink"); 62 | if *ctx.local.state { 63 | ctx.local.led.set_high(); 64 | *ctx.local.state = false; 65 | } else { 66 | ctx.local.led.set_low(); 67 | *ctx.local.state = true; 68 | } 69 | Systick::delay(1000.millis()).await; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /app/rtic/timer_interrupt_rtic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "timer_interrupt_rtic" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | embedded-hal = "0.2.7" 12 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 13 | rtic = { version = "2.0.1", features = [ "thumbv7-backend" ] } 14 | defmt = "0.3.5" 15 | defmt-rtt = "0.4.0" 16 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 17 | 18 | 19 | [package.metadata.docs.rs] 20 | features = [ 21 | "stm32f103", 22 | "rtic", 23 | "high", 24 | ] -------------------------------------------------------------------------------- /app/rtic/timer_interrupt_rtic/README.md: -------------------------------------------------------------------------------- 1 | # TIM 定时器中断-RTIC 2 | 3 | 这是一个 TIM 定时器中断的 RTIC 实现的示例。 4 | 5 | 该示例来自 hal 库的示例。 6 | 7 | ## 执行指令 8 | 9 | ```shell 10 | cargo rp timer_interrupt_rtic 11 | ``` 12 | 13 | ## 学习目标 14 | 15 | - 了解 TIM 定时器 16 | - 了解 RTIC 17 | 18 | ## 接线图 19 | 20 | ![](../../../images/wiring_diagram/3-1%20LED闪烁.jpg) 21 | -------------------------------------------------------------------------------- /app/spi/spi_hard_w25q64/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "spi_hard_w25q64" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = { version = "0.10.0", features = ["rt", "stm32f103", "medium"] } 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = { version = "0.3.1", features = ["print-defmt"] } 15 | embedded-dma = "0.2.0" 16 | nb = "1.1.0" 17 | unwrap-infallible = "0.1.5" 18 | heapless = "0.8.0" 19 | 20 | [dependencies.hardware] 21 | path = "../../../core/hardware" 22 | -------------------------------------------------------------------------------- /app/spi/spi_hard_w25q64/README.md: -------------------------------------------------------------------------------- 1 | # SPI 硬件读写 W25Q64 2 | 3 | 这是一个使用 SPI 硬件读写 W25Q64 的示例。 4 | 5 | {:02X}: 是一个格式化字符串,用于在 Rust 编程语言中将一个字节(u8 类型)转换为两位十六进制的字符串。例如,10 这个字节用{:02X}格式化后就是 0A,255 这个字节用{:02X}格式化后就是 FF。这里的 02 表示要用 0 来填充两位,如果不足两位的话。X 表示要用大写的字母来表示十六进制的数字,如果用 x 则表示用小写的字母。 6 | 7 | ## 执行指令 8 | 9 | ```shell 10 | cargo rp spi_hard_w25q64 11 | ``` 12 | 13 | ## 学习目标 14 | 15 | - 了解 SPI 通讯协议 16 | - 了解 W25Q64 非易失性存储器 17 | 18 | ## 接线图 19 | 20 | ![](../../../images/wiring_diagram/11-2%20硬件SPI读写W25Q64.jpg) 21 | -------------------------------------------------------------------------------- /app/spi/spi_nrf24l01/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "spi_nrf24l01" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = { version = "0.10.0", features = ["rt", "stm32f103", "medium"] } 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = { version = "0.3.1", features = ["print-defmt"] } 15 | nb = "1.1.0" 16 | unwrap-infallible = "0.1.5" 17 | heapless = "0.8.0" 18 | # SPI - 2.4 GHz 无线通信 19 | embedded-nrf24l01 = "0.2.0" 20 | -------------------------------------------------------------------------------- /app/spi/spi_nrf24l01/README.md: -------------------------------------------------------------------------------- 1 | # NRF24L01 2 | 3 | 这是一个使用 NRF24L01 SPI 2.4 GHz 无线通信的示例。 4 | 5 | ## 引脚 6 | 7 | ### NRF24L01 8 | 9 | - VCC: VCC 10 | - GND: GND 11 | - CSN: PB7 12 | - CE: PB6 13 | - MOSI: PB5 14 | - SCK: PB3 15 | - MISO: PB4 16 | 17 | ## 执行指令 18 | 19 | ```shell 20 | cargo rp spi_nrf24l01 21 | ``` 22 | 23 | ## 学习目标 24 | 25 | - 了解 NRF24L01 crate 26 | 27 | ## 接线图 28 | 29 | ![](../../../images/wiring_diagram/NRF24L01引脚图.jpg) 30 | -------------------------------------------------------------------------------- /app/spi/spi_soft_w25q64/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "spi_soft_w25q64" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = { version = "0.10.0", features = ["rt", "stm32f103", "medium"] } 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = { version = "0.3.1", features = ["print-defmt"] } 15 | embedded-dma = "0.2.0" 16 | nb = "1.1.0" 17 | unwrap-infallible = "0.1.5" 18 | heapless = "0.8.0" 19 | 20 | [dependencies.hardware] 21 | path = "../../../core/hardware" 22 | -------------------------------------------------------------------------------- /app/spi/spi_soft_w25q64/README.md: -------------------------------------------------------------------------------- 1 | # SPI 软件读写 W25Q64 2 | 3 | 这是一个使用 GPIO 模拟 SPI 读写 W25Q64 的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp spi_soft_w25q64 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解 SPI 通讯协议 14 | - 了解 W25Q64 非易失性存储器 15 | 16 | ## 接线图 17 | 18 | ![](../../../images/wiring_diagram/11-1%20模拟SPI读写W25Q64.jpg) 19 | -------------------------------------------------------------------------------- /app/spi/spi_w25q_crate/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "spi_w25q_crate" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = { version = "0.10.0", features = ["rt", "stm32f103", "medium"] } 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = { version = "0.3.1", features = ["print-defmt"] } 15 | embedded-dma = "0.2.0" 16 | nb = "1.1.0" 17 | unwrap-infallible = "0.1.5" 18 | heapless = "0.8.0" 19 | w25q = "0.2.9" 20 | 21 | [dependencies.hardware] 22 | path = "../../../core/hardware" 23 | -------------------------------------------------------------------------------- /app/spi/spi_w25q_crate/README.md: -------------------------------------------------------------------------------- 1 | # w25q crate 读写 W25Q64 2 | 3 | 这是一个使用 w25q crate 读写 W25Q64 的失败示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp spi_w25q_crate 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解 w25q crate 14 | 15 | ## 接线图 16 | 17 | ![](../../../images/wiring_diagram/11-2%20硬件SPI读写W25Q64.jpg) 18 | -------------------------------------------------------------------------------- /app/usart/serial_config/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serial_config" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | embedded-dma = "0.2.0" 16 | nb = "1.1.0" 17 | unwrap-infallible = "0.1.5" 18 | 19 | [dependencies.hardware] 20 | path = "../../../core/hardware" 21 | -------------------------------------------------------------------------------- /app/usart/serial_config/README.md: -------------------------------------------------------------------------------- 1 | # 串行接口配置 2 | 3 | ## 执行指令 4 | 5 | ```shell 6 | cargo rp serial_config 7 | ``` 8 | 9 | ## 学习目标 10 | 11 | - 了解串口接线 12 | - 了解串口配置 13 | - 发送一个字节 14 | - 端口工具接受字节 15 | - 了解 minicom/cutecom 端口工具 16 | 17 | ## 接线图 18 | 19 | ![](../../../images/wiring_diagram/9-1%20串口发送.jpg) 20 | -------------------------------------------------------------------------------- /app/usart/serial_continuous_tx_and_rx/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serial_continuous_tx_and_rx" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | embedded-dma = "0.2.0" 16 | nb = "1.1.0" 17 | unwrap-infallible = "0.1.5" 18 | 19 | 20 | [dependencies.hardware] 21 | path = "../../../core/hardware" 22 | -------------------------------------------------------------------------------- /app/usart/serial_continuous_tx_and_rx/README.md: -------------------------------------------------------------------------------- 1 | # 串行接口连续发送与接收 2 | 3 | 这是一个使用封装的函数进行发送与接收的示例。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp serial_continuous_tx_and_rx 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 使用封装的函数进行发送与接收 14 | - 字符串 15 | - 数字 16 | 17 | ## 接线图 18 | 19 | ![](../../../images/wiring_diagram/9-1%20串口发送.jpg) 20 | -------------------------------------------------------------------------------- /app/usart/serial_fmt/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serial_fmt" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | embedded-dma = "0.2.0" 16 | nb = "1.1.0" 17 | unwrap-infallible = "0.1.5" 18 | 19 | [dependencies.hardware] 20 | path = "../../../core/hardware" 21 | -------------------------------------------------------------------------------- /app/usart/serial_fmt/README.md: -------------------------------------------------------------------------------- 1 | # 串行接口写入格式化字符串 2 | 3 | ## 执行指令 4 | 5 | ```shell 6 | cargo rp serial_fmt 7 | ``` 8 | 9 | ## 学习目标 10 | 11 | - 串行接口写入格式化字符串 12 | 13 | ## 接线图 14 | 15 | ![](../../../images/wiring_diagram/9-1%20串口发送.jpg) 16 | -------------------------------------------------------------------------------- /app/usart/serial_fmt/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![allow(clippy::empty_loop)] 4 | 5 | use core::fmt::Write; 6 | 7 | use defmt::println; 8 | use defmt_rtt as _; 9 | use panic_probe as _; 10 | 11 | use cortex_m::asm::wfi; 12 | use cortex_m_rt::entry; 13 | use stm32f1xx_hal::pac; 14 | use stm32f1xx_hal::prelude::_stm32_hal_afio_AfioExt; 15 | use stm32f1xx_hal::prelude::_stm32_hal_flash_FlashExt; 16 | use stm32f1xx_hal::prelude::_stm32_hal_gpio_GpioExt; 17 | use stm32f1xx_hal::rcc::RccExt; 18 | use stm32f1xx_hal::serial; 19 | use stm32f1xx_hal::serial::Serial; 20 | use stm32f1xx_hal::time::U32Ext; 21 | use stm32f1xx_hal::timer::SysTimerExt; 22 | 23 | #[entry] 24 | fn main() -> ! { 25 | // 获取对外设的访问对象 26 | let cp = cortex_m::Peripherals::take().unwrap(); 27 | let dp = pac::Peripherals::take().unwrap(); 28 | 29 | let mut flash = dp.FLASH.constrain(); 30 | let rcc = dp.RCC.constrain(); 31 | let mut afio = dp.AFIO.constrain(); 32 | let syst = cp.SYST; 33 | 34 | let mut gpioa = dp.GPIOA.split(); 35 | 36 | // 冻结系统中所有时钟的配置,并将冻结的频率存储在时钟中 37 | let clocks = rcc.cfgr.freeze(&mut flash.acr); 38 | 39 | // 具有自定义精度的阻塞延迟函数 40 | let mut _delay = syst.delay(&clocks); 41 | 42 | // USART1 43 | let tx = gpioa.pa9.into_alternate_push_pull(&mut gpioa.crh); 44 | let rx = gpioa.pa10; 45 | 46 | // 设置usart设备。取得USART寄存器和tx/rx引脚的所有权。其余寄存器用于启用和配置设备。 47 | println!("load serial..."); 48 | let serial = Serial::new( 49 | dp.USART1, 50 | (tx, rx), 51 | &mut afio.mapr, 52 | serial::Config::default() 53 | .baudrate(9600.bps()) 54 | .stopbits(serial::StopBits::STOP2) 55 | .wordlength_9bits() 56 | .parity_odd(), 57 | &clocks, 58 | ); 59 | 60 | // 将串行结构拆分为接收和发送部分 61 | let (mut tx, _rx) = serial.split(); 62 | 63 | let number = 103; 64 | writeln!(tx, "Hello formatted string {}", number).unwrap(); 65 | 66 | // for windows 67 | // write!(tx, "Hello formatted string {}\r\n", number).unwrap(); 68 | 69 | loop { 70 | wfi(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /app/usart/serial_hex_packet/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serial_hex_packet" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | embedded-dma = "0.2.0" 16 | nb = "1.1.0" 17 | unwrap-infallible = "0.1.5" 18 | 19 | 20 | [dependencies.hardware] 21 | path = "../../../core/hardware" 22 | -------------------------------------------------------------------------------- /app/usart/serial_hex_packet/README.md: -------------------------------------------------------------------------------- 1 | # 串行接口收发 HEX 数据包 2 | 3 | 这是一个使用串行接口收发 HEX 数据包的示例。 4 | 5 | 要求: 6 | 7 | - 使用中断接收数据 8 | - 使用状态机进行状态转换 9 | - 使用标识符进行数据接收标识 10 | - 注意客户端切换到 HEX 模式发送 11 | 12 | ## 执行指令 13 | 14 | ```shell 15 | cargo rp serial_hex_packet 16 | ``` 17 | 18 | ## 学习目标 19 | 20 | - 数据包协议 21 | - 数据传输校验方式 22 | - 收发 HEX 数据包 23 | 24 | ## 接线图 25 | 26 | ![](../../../images/wiring_diagram/9-3%20串口收发HEX数据包.jpg) 27 | -------------------------------------------------------------------------------- /app/usart/serial_interrupt_idle/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serial_interrupt_idle" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | embedded-dma = "0.2.0" 16 | nb = "1.1.0" 17 | unwrap-infallible = "0.1.5" 18 | 19 | [dependencies.hardware] 20 | path = "../../../core/hardware" 21 | -------------------------------------------------------------------------------- /app/usart/serial_interrupt_idle/README.md: -------------------------------------------------------------------------------- 1 | # 串行接口中断 2 | 3 | ## 执行指令 4 | 5 | ```shell 6 | cargo rp serial_interrupt_idle 7 | ``` 8 | 9 | ## 学习目标 10 | 11 | - 串行接口中断 12 | 13 | ## 接线图 14 | 15 | ![](../../../images/wiring_diagram/9-1%20串口发送.jpg) 16 | -------------------------------------------------------------------------------- /app/usart/serial_reconfigure/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serial_reconfigure" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | embedded-dma = "0.2.0" 16 | nb = "1.1.0" 17 | unwrap-infallible = "0.1.5" 18 | 19 | 20 | [dependencies.hardware] 21 | path = "../../../core/hardware" 22 | -------------------------------------------------------------------------------- /app/usart/serial_reconfigure/README.md: -------------------------------------------------------------------------------- 1 | # 串行接口重新配置 2 | 3 | 这是一个串行接口重新配置的示例。在运行过程中重新配置波特率。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp serial_reconfigure 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解串口接线 14 | - 了解串口配置 15 | - 发送一个字节 16 | - 端口工具接受字节 17 | - 了解 minicom/cutecom 端口工具 18 | 19 | ## 接线图 20 | 21 | ![](../../../images/wiring_diagram/9-1%20串口发送.jpg) 22 | -------------------------------------------------------------------------------- /app/usart/serial_text_packet/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serial_text_packet" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = { version = "0.10.0", features = ["rt", "stm32f103", "medium"] } 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = { version = "0.3.1", features = ["print-defmt"] } 15 | embedded-dma = "0.2.0" 16 | nb = "1.1.0" 17 | unwrap-infallible = "0.1.5" 18 | heapless = "0.8.0" 19 | 20 | [dependencies.hardware] 21 | path = "../../../core/hardware" 22 | -------------------------------------------------------------------------------- /app/usart/serial_text_packet/README.md: -------------------------------------------------------------------------------- 1 | # 串行接口收发文本数据包 2 | 3 | 这是一个使用串行接口收发文本数据包的示例。通过指令控制 LED 灯是否点亮。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp serial_text_packet 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 数据包协议 14 | - 数据传输校验方式 15 | - 收发文本数据包 16 | 17 | ## 接线图 18 | 19 | ![](../../../images/wiring_diagram/9-4%20串口收发文本数据包.jpg) 20 | -------------------------------------------------------------------------------- /app/usart/serial_tx_and_rx/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serial_tx_and_rx" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | embedded-dma = "0.2.0" 16 | nb = "1.1.0" 17 | unwrap-infallible = "0.1.5" 18 | 19 | 20 | [dependencies.hardware] 21 | path = "../../../core/hardware" 22 | -------------------------------------------------------------------------------- /app/usart/serial_tx_and_rx/README.md: -------------------------------------------------------------------------------- 1 | # 串行接口发送与接收 2 | 3 | 这是一个串行接口重新配置的示例。在运行过程中重新配置波特率。 4 | 5 | ## 执行指令 6 | 7 | ```shell 8 | cargo rp serial_tx_and_rx 9 | ``` 10 | 11 | ## 学习目标 12 | 13 | - 了解串口接线 14 | - 了解串口配置 15 | - 发送一个字节 16 | - 端口工具接受字节 17 | - 了解 minicom/cutecom 端口工具 18 | 19 | ## 接线图 20 | 21 | ![](../../../images/wiring_diagram/9-1%20串口发送.jpg) 22 | -------------------------------------------------------------------------------- /app/wdg/iwdg/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iwdg" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | 17 | [dependencies.hardware] 18 | path = "../../../core/hardware" 19 | -------------------------------------------------------------------------------- /app/wdg/iwdg/README.md: -------------------------------------------------------------------------------- 1 | # 独立看门狗 2 | 3 | 这是一个独立看门狗的示例。独立工作,对时间精度要求较低。 4 | 5 | 程序正常运行时,第二行显示 RST; 6 | 按住按键 5s 不放模拟程序卡死,看门狗触发复位, 第二行显示 IWDGRST。 7 | 8 | ## 执行指令 9 | 10 | ```shell 11 | cargo rp iwdg 12 | ``` 13 | 14 | ## 学习目标 15 | 16 | - 了解独立看门狗 17 | - 超时时间:0.1ms ~ 26214.4ms 18 | 19 | ## 接线图 20 | 21 | ![](../../../images/wiring_diagram/14-1%20独立看门狗.jpg) 22 | -------------------------------------------------------------------------------- /app/wdg/wwdg/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wwdg" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 10 | cortex-m-rt = "0.7.3" 11 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 12 | defmt = "0.3.5" 13 | defmt-rtt = "0.4.0" 14 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 15 | 16 | 17 | [dependencies.hardware] 18 | path = "../../../core/hardware" 19 | -------------------------------------------------------------------------------- /app/wdg/wwdg/README.md: -------------------------------------------------------------------------------- 1 | # 窗口看门狗 2 | 3 | 这是一个窗口看门狗的示例。要求看门狗在精确计时窗口起作用。 4 | 5 | 示例中设置超时时间 50ms、窗口时间 30ms。 6 | 7 | 超时时间=50ms/(1/36000MHz)/4096/8(预分频系数) ~= 54.9 => T[5:0]+1 => T[5:0] = 54 8 | 窗口时间=30ms/(1/36000MHz)/4096/8(预分频系数) ~= 32.9 => T[5:0]-W[5:0] => 54-33 => W[5:0]=21 9 | 10 | 注意: 11 | 如果你的主循环的执行时间可能会超过窗口看门狗的超时时间,或者你不能保证每次循环时窗口看门狗的计数器的值都在窗口值以下,你就需要更加谨慎地"喂狗"。你可能需要在你的代码中添加检查,以确保只在窗口看门狗的计数器的值在窗口值以下时才"喂狗"。 12 | 13 | ## 执行指令 14 | 15 | ```shell 16 | cargo rp wwdg 17 | ``` 18 | 19 | ## 学习目标 20 | 21 | - 窗口看门狗 22 | - 超时时间:113us ~ 58.25ms 23 | 24 | ## 接线图 25 | 26 | ![](../../../images/wiring_diagram/14-2%20窗口看门狗.jpg) 27 | -------------------------------------------------------------------------------- /bak/link.x: -------------------------------------------------------------------------------- 1 | /* Memory layout of the LM3S6965 microcontroller */ 2 | /* 1K = 1 KiBi = 1024 bytes */ 3 | MEMORY 4 | { 5 | FLASH : ORIGIN = 0x00000000, LENGTH = 256K 6 | RAM : ORIGIN = 0x20000000, LENGTH = 64K 7 | } 8 | 9 | /* The entry point is the reset handler */ 10 | ENTRY(Reset); 11 | 12 | EXTERN(RESET_VECTOR); 13 | 14 | SECTIONS 15 | { 16 | .vector_table ORIGIN(FLASH) : 17 | { 18 | /* First entry: initial Stack Pointer value */ 19 | LONG(ORIGIN(RAM) + LENGTH(RAM)); 20 | 21 | /* Second entry: reset vector */ 22 | KEEP(*(.vector_table.reset_vector)); 23 | } > FLASH 24 | 25 | .text : 26 | { 27 | *(.text .text.*); 28 | } > FLASH 29 | 30 | .rodata : 31 | { 32 | *(.rodata .rodata.*); 33 | } > FLASH 34 | 35 | .bss : 36 | { 37 | _sbss = .; 38 | *(.bss .bss.*); 39 | _ebss = .; 40 | } > RAM 41 | 42 | .data : AT(ADDR(.rodata) + SIZEOF(.rodata)) 43 | { 44 | _sdata = .; 45 | *(.data .data.*); 46 | _edata = .; 47 | } > RAM 48 | 49 | _sidata = LOADADDR(.data); 50 | 51 | /DISCARD/ : 52 | { 53 | *(.ARM.exidx .ARM.exidx.*); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /bak/signal_simulation.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """信号模拟 3 | 4 | 5 | # 外设 6 | uart6: Python.PythonPeripheral @ sysbus 0x7000F410 7 | size: 0x4 8 | initable: true 9 | filename: "/home/one/Documents/code/RustEmbedProject/stm32f103-tutorial/bak/signal_simulation.py" 10 | 11 | # 写入文件 12 | scripts/platforms/cpus/stm32f103.repl 13 | """ 14 | 15 | print("xxx") 16 | if request.isInit: 17 | lastVal = 0 18 | elif request.isRead: 19 | request.value = lastVal 20 | elif request.isWrite: 21 | lastVal = request.value 22 | 23 | self.NoisyLog("%s on REPEATER at 0x%x, value 0x%x" % 24 | (str(request.type), request.offset, request.value)) 25 | -------------------------------------------------------------------------------- /bak/udev/rules.d/49-stlinkv1.rules: -------------------------------------------------------------------------------- 1 | # STM32 discovery boards, with onboard st/linkv1 2 | # ie, STM32VL 3 | 4 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3744", \ 5 | MODE:="0666", \ 6 | SYMLINK+="stlinkv1_%n" 7 | 8 | # If you share your linux system with other users, or just don't like the 9 | # idea of write permission for everybody, you can replace MODE:="0666" with 10 | # OWNER:="yourusername" to create the device owned by you, or with 11 | # GROUP:="somegroupname" and mange access using standard unix groups. 12 | -------------------------------------------------------------------------------- /bak/udev/rules.d/49-stlinkv2-1.rules: -------------------------------------------------------------------------------- 1 | # STM32 nucleo boards, with onboard st/linkv2-1 2 | # ie, STM32F0, STM32F4. 3 | # STM32VL has st/linkv1, which is quite different 4 | 5 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374a", \ 6 | MODE:="0666", \ 7 | SYMLINK+="stlinkv2-1_%n" 8 | 9 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", \ 10 | MODE:="0666", \ 11 | SYMLINK+="stlinkv2-1_%n" 12 | 13 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3752", \ 14 | MODE:="0666", \ 15 | SYMLINK+="stlinkv2-1_%n" 16 | 17 | # If you share your linux system with other users, or just don't like the 18 | # idea of write permission for everybody, you can replace MODE:="0666" with 19 | # OWNER:="yourusername" to create the device owned by you, or with 20 | # GROUP:="somegroupname" and mange access using standard unix groups. 21 | -------------------------------------------------------------------------------- /bak/udev/rules.d/49-stlinkv2.rules: -------------------------------------------------------------------------------- 1 | # STM32 discovery boards, with onboard st/linkv2 2 | # ie, STM32L, STM32F4. 3 | # STM32VL has st/linkv1, which is quite different 4 | 5 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", \ 6 | MODE:="0666", \ 7 | SYMLINK+="stlinkv2_%n" 8 | 9 | # If you share your linux system with other users, or just don't like the 10 | # idea of write permission for everybody, you can replace MODE:="0666" with 11 | # OWNER:="yourusername" to create the device owned by you, or with 12 | # GROUP:="somegroupname" and mange access using standard unix groups. 13 | -------------------------------------------------------------------------------- /bak/udev/rules.d/49-stlinkv3.rules: -------------------------------------------------------------------------------- 1 | # STLink V3SET in Dual CDC mode 2 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3752", \ 3 | MODE:="0666", \ 4 | SYMLINK+="stlinkv3_%n" 5 | 6 | # STLink V3SET in Dual CDC mode 7 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3753", \ 8 | MODE:="0666", \ 9 | SYMLINK+="stlinkv3_%n" 10 | 11 | # STLink V3SET MINIE 12 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3754", \ 13 | MODE:="0666", \ 14 | SYMLINK+="stlinkv3_%n" 15 | 16 | # STLink V3SET 17 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374d", \ 18 | MODE:="0666", \ 19 | SYMLINK+="stlinkv3_%n" 20 | 21 | # STLink V3SET 22 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374e", \ 23 | MODE:="0666", \ 24 | SYMLINK+="stlinkv3_%n" 25 | 26 | # STLink V3SET in normal mode 27 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374f", \ 28 | MODE:="0666", \ 29 | SYMLINK+="stlinkv3_%n" 30 | 31 | # If you share your linux system with other users, or just don't like the 32 | # idea of write permission for everybody, you can replace MODE:="0666" with 33 | # OWNER:="yourusername" to create the device owned by you, or with 34 | # GROUP:="somegroupname" and mange access using standard unix groups. 35 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | //! This build script copies the `memory.x` file from the crate root into 2 | //! a directory where the linker can always find it at build time. 3 | //! For many projects this is optional, as the linker always searches the 4 | //! project root directory -- wherever `Cargo.toml` is. However, if you 5 | //! are using a workspace or have a more complicated build setup, this 6 | //! build script becomes required. Additionally, by requesting that 7 | //! Cargo re-run the build script whenever `memory.x` is changed, 8 | //! updating `memory.x` ensures a rebuild of the application with the 9 | //! new memory settings. 10 | 11 | use std::env; 12 | use std::fs::File; 13 | use std::io::Write; 14 | use std::path::PathBuf; 15 | 16 | fn main() { 17 | // Put `memory.x` in our output directory and ensure it's 18 | // on the linker search path. 19 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 20 | File::create(out.join("memory.x")) 21 | .unwrap() 22 | .write_all(include_bytes!("memory.x")) 23 | .unwrap(); 24 | println!("cargo:rustc-link-search={}", out.display()); 25 | 26 | // By default, Cargo will re-run a build script whenever 27 | // any file in the project changes. By specifying `memory.x` 28 | // here, we ensure the build script is only re-run when 29 | // `memory.x` is changed. 30 | println!("cargo:rerun-if-changed=memory.x"); 31 | } 32 | -------------------------------------------------------------------------------- /core/bindgen_hello/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bindgen_hello" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | harness = false 8 | 9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 10 | [dependencies] 11 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 12 | cortex-m-rt = "0.7.3" 13 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 14 | defmt = "0.3" 15 | defmt-rtt = "0.4.0" 16 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 17 | 18 | [dev-dependencies] 19 | defmt-test = "0.3.0" 20 | 21 | [build-dependencies] 22 | bindgen = "0.66.1" 23 | cc = "1.0.83" 24 | glob = "0.3.1" 25 | 26 | [[test]] 27 | name = "hello_demo" 28 | path = "tests/hello_demo.rs" 29 | harness = false 30 | -------------------------------------------------------------------------------- /core/bindgen_hello/README.md: -------------------------------------------------------------------------------- 1 | # FFI Hello 2 | 3 | 这是一个使用 Rust FFI 绑定 C 语言的案例。 4 | 5 | ## 安装 ARM GCC 编译环境 6 | 7 | ```shell 8 | sudo pacman -S arm-none-eabi-gcc arm-none-eabi-newlib 9 | ``` 10 | 11 | ## 编译 12 | 13 | 绑定是动态生成。 14 | 15 | ```shell 16 | cargo build --target thumbv7m-none-eabi --package bindgen_hello 17 | ``` 18 | 19 | ## lib 测试 20 | 21 | ```shell 22 | cargo test --target thumbv7m-none-eabi -p bindgen_hello 23 | ``` 24 | 25 | ## 指定测试 26 | 27 | ```shell 28 | cargo test --target thumbv7m-none-eabi --package bindgen_hello --test hello_demo 29 | ``` 30 | -------------------------------------------------------------------------------- /core/bindgen_hello/build.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | 3 | use bindgen::CargoCallbacks; 4 | 5 | fn main() { 6 | cc::Build::new() 7 | // 编译单个文件 8 | // .file("hello/hello.c") 9 | // 正则匹配多个编译文件 10 | .files(glob::glob("hello/*.c").unwrap().filter_map(Result::ok)) 11 | // 将多个目录添加到包含路径。-I 12 | .includes(&["hello"]) 13 | // 配置所有对象文件和静态文件的输出目录 14 | // .out_dir("out_dir") 15 | // 设置编译目标, 默认会自动从环境中抓取 TARGET 变量 16 | // .target("thumbv7m-none-eabi") 17 | // 定义是否应为货物发出元数据,使其能够 自动链接二进制文件。 18 | .cargo_metadata(true) 19 | // 运行编译器,生成output文件 20 | .compile("hello"); 21 | 22 | // bindgen::Builder是bindgen的主要入口点,允许您为生成的绑定构建选项。 23 | let bindings = bindgen::Builder::default() 24 | // 我们要为其生成绑定的输入标头。 25 | .header("hello/hello.h") 26 | .header("hello/bar.h") 27 | .use_core() 28 | .bitfield_enum("USE_STDPERIPH_DRIVER") 29 | .bitfield_enum("STM32F10X_MD") 30 | // 当包含的任何头文件发生变化时,告诉货物使已构建的板条箱失效。 31 | .parse_callbacks(Box::new(CargoCallbacks)) 32 | // 完成构建器并生成绑定。 33 | .generate() 34 | .expect("Unable to generate bindings"); 35 | 36 | // 将绑定写入 bindings.rs 文件。 37 | let out_path = PathBuf::from("./hello"); 38 | bindings 39 | .write_to_file(out_path.join("bindings.rs")) 40 | .expect("Couldn't write bindings!"); 41 | } 42 | -------------------------------------------------------------------------------- /core/bindgen_hello/hello/bar.c: -------------------------------------------------------------------------------- 1 | /* 函数返回两个数中较大的那个数 */ 2 | int max(int num1, int num2) 3 | { 4 | /* 局部变量声明 */ 5 | int result; 6 | 7 | if (num1 > num2) { 8 | result = num1; 9 | } else { 10 | result = num2; 11 | } 12 | return result; 13 | } -------------------------------------------------------------------------------- /core/bindgen_hello/hello/bar.h: -------------------------------------------------------------------------------- 1 | int max(int num1, int num2); -------------------------------------------------------------------------------- /core/bindgen_hello/hello/bindings.rs: -------------------------------------------------------------------------------- 1 | /* automatically generated by rust-bindgen 0.66.1 */ 2 | 3 | extern "C" { 4 | pub fn Hello() -> ::core::ffi::c_int; 5 | } 6 | extern "C" { 7 | pub fn Max() -> ::core::ffi::c_int; 8 | } 9 | extern "C" { 10 | pub fn max(num1: ::core::ffi::c_int, num2: ::core::ffi::c_int) -> ::core::ffi::c_int; 11 | } 12 | -------------------------------------------------------------------------------- /core/bindgen_hello/hello/hello.c: -------------------------------------------------------------------------------- 1 | #include "bar.h" 2 | 3 | int Hello() { 4 | return 42; 5 | } 6 | 7 | int Max() { 8 | return max(10,20); 9 | } 10 | -------------------------------------------------------------------------------- /core/bindgen_hello/hello/hello.h: -------------------------------------------------------------------------------- 1 | int Hello(); 2 | int Max(); 3 | -------------------------------------------------------------------------------- /core/bindgen_hello/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![allow(non_upper_case_globals)] 4 | #![allow(non_camel_case_types)] 5 | #![allow(non_snake_case)] 6 | 7 | include!(concat!("../hello/bindings.rs")); 8 | -------------------------------------------------------------------------------- /core/bindgen_hello/tests/hello_demo.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use bindgen_hello::max; 5 | use bindgen_hello::Hello; 6 | 7 | use defmt_rtt as _; 8 | use panic_probe as _; 9 | 10 | use stm32f1xx_hal as _; 11 | 12 | #[cfg(test)] 13 | #[defmt_test::tests] 14 | mod unit_tests { 15 | use super::*; 16 | 17 | use defmt::assert; 18 | use defmt::assert_eq; 19 | 20 | #[test] 21 | fn it_works() { 22 | assert!(true) 23 | } 24 | 25 | #[test] 26 | fn it_hello() { 27 | assert_eq!(unsafe { Hello() }, 42) 28 | } 29 | 30 | #[test] 31 | fn it_max() { 32 | assert_eq!(unsafe { max(10, 20) }, 20) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /core/ffi_hello/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ffi_hello" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | harness = false 8 | 9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 10 | [dependencies] 11 | cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} 12 | cortex-m-rt = "0.7.3" 13 | stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103", "medium"]} 14 | defmt = "0.3" 15 | defmt-rtt = "0.4.0" 16 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 17 | 18 | [dev-dependencies] 19 | defmt-test = "0.3.0" 20 | 21 | [build-dependencies] 22 | bindgen = "0.66.1" 23 | cc = "1.0.83" 24 | glob = "0.3.1" 25 | -------------------------------------------------------------------------------- /core/ffi_hello/README.md: -------------------------------------------------------------------------------- 1 | # FFI Hello 2 | 3 | 这是一个使用 Rust FFI 绑定 C 语言的案例。 4 | 5 | ## 安装 ARM GCC 编译环境 6 | 7 | ```shell 8 | sudo pacman -S arm-none-eabi-gcc arm-none-eabi-newlib 9 | ``` 10 | 11 | ## 编译 12 | 13 | 绑定是动态生成。 14 | 15 | ```shell 16 | cargo build --package ffi_hello 17 | ``` 18 | 19 | ## 测试 20 | 21 | ```shell 22 | cargo test --target thumbv7m-none-eabi -p ffi_hello 23 | ``` 24 | -------------------------------------------------------------------------------- /core/ffi_hello/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | cc::Build::new() 3 | // 编译单个文件 4 | // .file("hello/hello.c") 5 | // 正则匹配多个编译文件 6 | .files(glob::glob("hello/*.c").unwrap().filter_map(Result::ok)) 7 | // 将多个目录添加到包含路径。-I 8 | .includes(&["hello"]) 9 | // 配置所有对象文件和静态文件的输出目录 10 | // .out_dir("out_dir") 11 | // 设置编译目标, 默认会自动从环境中抓取 TARGET 变量 12 | // .target("thumbv7m-none-eabi") 13 | // 定义是否应为货物发出元数据,使其能够 自动链接二进制文件。 14 | .cargo_metadata(true) 15 | // 运行编译器,生成output文件 16 | .compile("hello"); 17 | } 18 | -------------------------------------------------------------------------------- /core/ffi_hello/hello/bar.c: -------------------------------------------------------------------------------- 1 | int AD_Value[4]; 2 | 3 | /* 函数返回两个数中较大的那个数 */ 4 | int max(int num1, int num2) 5 | { 6 | /* 局部变量声明 */ 7 | int result; 8 | 9 | if (num1 > num2) { 10 | result = num1; 11 | } else { 12 | result = num2; 13 | } 14 | return result; 15 | } -------------------------------------------------------------------------------- /core/ffi_hello/hello/bar.h: -------------------------------------------------------------------------------- 1 | int max(int num1, int num2); 2 | // 导出变量 3 | extern int AD_Value[4]; 4 | -------------------------------------------------------------------------------- /core/ffi_hello/hello/hello.c: -------------------------------------------------------------------------------- 1 | #include "bar.h" 2 | 3 | int Hello() { 4 | return 42; 5 | } 6 | -------------------------------------------------------------------------------- /core/ffi_hello/hello/hello.h: -------------------------------------------------------------------------------- 1 | int Hello(); 2 | -------------------------------------------------------------------------------- /core/ffi_hello/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use defmt_rtt as _; 5 | use panic_probe as _; 6 | 7 | use stm32f1xx_hal as _; 8 | 9 | #[allow(unused)] 10 | extern "C" { 11 | #[link_name = "Hello"] 12 | pub fn hello() -> i32; 13 | pub fn max(num1: i32, num2: i32) -> i32; 14 | } 15 | 16 | #[cfg(test)] 17 | #[defmt_test::tests] 18 | mod unit_tests { 19 | use super::*; 20 | 21 | use defmt::assert; 22 | 23 | #[test] 24 | fn it_works() { 25 | assert!(true) 26 | } 27 | 28 | #[test] 29 | fn it_hello() { 30 | assert_eq!(unsafe { hello() }, 42) 31 | } 32 | 33 | #[test] 34 | fn it_max() { 35 | assert_eq!(unsafe { max(10, 20) }, 20) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /core/hardware/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hardware" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | harness = false 8 | 9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 10 | [dependencies] 11 | cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } 12 | cortex-m-rt = "0.7.3" 13 | embedded-hal = "0.2.7" 14 | stm32f1xx-hal = { version = "0.10.0", features = ["rt", "stm32f103", "medium"] } 15 | defmt = "0.3" 16 | defmt-rtt = "0.4.0" 17 | panic-probe = { version = "0.3.1", features = ["print-defmt"] } 18 | nb = "1.1.0" 19 | unwrap-infallible = "0.1.5" 20 | numtoa = "0.2.4" 21 | heapless = "0.8.0" 22 | 23 | 24 | [dev-dependencies] 25 | defmt-test = "0.3.0" 26 | -------------------------------------------------------------------------------- /core/hardware/README.md: -------------------------------------------------------------------------------- 1 | # 常用外设工具库封装 2 | 3 | 这是一个将常用的外设封装为工具库。 4 | 5 | ## 工具列表 6 | 7 | - KEY 按键 8 | - OLED 显示屏 9 | - Serial 串行接口 10 | - I2C 软件读写 MPU6050 6 轴姿态传感器 11 | - I2C 硬件读写 MPU6050 6 轴姿态传感器 12 | - SPI 软件读写 W25Q64 非易失性存储器 13 | - SPI 硬件读写 W25Q64 非易失性存储器 14 | -------------------------------------------------------------------------------- /core/hardware/src/flash_store/mod.rs: -------------------------------------------------------------------------------- 1 | //!内部 FLASH 2 | pub mod flash_rw; 3 | pub use flash_rw::FlashStore; 4 | 5 | pub mod store; 6 | -------------------------------------------------------------------------------- /core/hardware/src/key.rs: -------------------------------------------------------------------------------- 1 | //! KEY 按键工具库 2 | 3 | use embedded_hal::{digital::v2::InputPin, prelude::_embedded_hal_blocking_delay_DelayMs}; 4 | use stm32f1xx_hal::timer::SysDelay; 5 | 6 | /// 获取按键的状态 7 | /// 按键是否按下 8 | pub fn get_key_status(key1: &mut Pin, delay: &mut SysDelay) -> bool 9 | where 10 | Pin: InputPin, 11 | ::Error: core::fmt::Debug, 12 | { 13 | if key1.is_low().unwrap() { 14 | // 按键按下抖动 15 | delay.delay_ms(20_u16); 16 | // 按着不动, 松手后跳出循环 17 | while key1.is_low().unwrap() {} 18 | // 按键松开抖动 19 | delay.delay_ms(20_u16); 20 | 21 | return true; 22 | } 23 | 24 | false 25 | } 26 | -------------------------------------------------------------------------------- /core/hardware/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use panic_probe as _; 5 | 6 | pub mod flash_store; 7 | pub mod key; 8 | pub mod mpu6050; 9 | pub mod oled; 10 | pub mod serial; 11 | pub mod syst; 12 | pub mod w25q64; 13 | -------------------------------------------------------------------------------- /core/hardware/src/mpu6050/conf.rs: -------------------------------------------------------------------------------- 1 | //!配置 2 | pub const DEFAULT_SLAVE_ADDR: u8 = 0x68; 3 | 4 | // 采样率分频,典型值:0x07(125Hz) 5 | pub const MPU6050_SMPLRT_DIV: u8 = 0x19; 6 | // 低通滤波频率,典型值:0x06(5Hz) 7 | pub const MPU6050_CONFIG: u8 = 0x1A; 8 | // 陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s) 9 | pub const MPU6050_GYRO_CONFIG: u8 = 0x1B; 10 | // 加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz) 11 | pub const MPU6050_ACCEL_CONFIG: u8 = 0x1C; 12 | 13 | // 存储最近的X轴、Y轴、Z轴加速度感应器的测量值 14 | pub const MPU6050_ACCEL_XOUT_H: u8 = 0x3B; 15 | pub const MPU6050_ACCEL_XOUT_L: u8 = 0x3C; 16 | pub const MPU6050_ACCEL_YOUT_H: u8 = 0x3D; 17 | pub const MPU6050_ACCEL_YOUT_L: u8 = 0x3E; 18 | pub const MPU6050_ACCEL_ZOUT_H: u8 = 0x3F; 19 | pub const MPU6050_ACCEL_ZOUT_L: u8 = 0x40; 20 | 21 | // 存储的最近温度传感器的测量值 22 | pub const MPU6050_TEMP_OUT_H: u8 = 0x41; 23 | pub const MPU6050_TEMP_OUT_L: u8 = 0x42; 24 | 25 | // 存储最近的X轴、Y轴、Z轴陀螺仪感应器的测量值 26 | pub const MPU6050_GYRO_XOUT_H: u8 = 0x43; 27 | pub const MPU6050_GYRO_XOUT_L: u8 = 0x44; 28 | pub const MPU6050_GYRO_YOUT_H: u8 = 0x45; 29 | pub const MPU6050_GYRO_YOUT_L: u8 = 0x46; 30 | pub const MPU6050_GYRO_ZOUT_H: u8 = 0x47; 31 | pub const MPU6050_GYRO_ZOUT_L: u8 = 0x48; 32 | 33 | // 电源管理,典型值:0x00(正常启用) 34 | pub const MPU6050_PWR_MGMT_1: u8 = 0x6B; 35 | pub const MPU6050_PWR_MGMT_2: u8 = 0x6C; 36 | // IIC地址寄存器(默认数值0x68,只读) 37 | pub const MPU6050_WHO_AM_I: u8 = 0x75; 38 | -------------------------------------------------------------------------------- /core/hardware/src/mpu6050/mod.rs: -------------------------------------------------------------------------------- 1 | //! 软件I2C读写MPU6050 2 | //! MPU6050 是一个6轴姿态传感器,可以测量芯片自身X、Y、Z轴的加速度、角速度参数, 3 | //! 通过数据融合,可进一步得到姿态角,常应用于平衡车、飞行器等需要检测自身姿态的场景。 4 | pub mod conf; 5 | pub mod mpu6050_hal; 6 | pub mod mpu6050_reg; 7 | 8 | /// 加速度和角速度数据 9 | #[derive(Default)] 10 | pub struct AccelGyroData { 11 | pub acc_x: i16, 12 | pub acc_y: i16, 13 | pub acc_z: i16, 14 | pub gyro_x: i16, 15 | pub gyro_y: i16, 16 | pub gyro_z: i16, 17 | } 18 | -------------------------------------------------------------------------------- /core/hardware/src/oled/mod.rs: -------------------------------------------------------------------------------- 1 | //! OLED 显示屏 2 | #![allow(unused)] 3 | 4 | pub mod font; 5 | pub mod simple; 6 | pub mod utils; 7 | 8 | pub use font::OLED_FONT; 9 | pub use utils::OLED; 10 | -------------------------------------------------------------------------------- /core/hardware/src/oled/simple.rs: -------------------------------------------------------------------------------- 1 | //! 简单的 OLED 实例 2 | 3 | use super::OLED; 4 | 5 | use stm32f1xx_hal::gpio::{self, IOPinSpeed, OpenDrain, Output, OutputSpeed, PB8, PB9}; 6 | 7 | /// OLEDTY 对象别名 8 | pub type OLEDTY = OLED>, PB9>>; 9 | 10 | /// 初始化 OLED 显示屏引脚 11 | /// pin: pb8、pb9 12 | /// ```rust 13 | /// use oled; 14 | /// let mut oled = oled::simple::init_oled(gpiob.pb8, gpiob.pb9, &mut gpiob.crh); 15 | /// oled.show_string(1, 1, "hallo"); 16 | /// ``` 17 | pub fn init_oled( 18 | pb8: PB8, 19 | pb9: PB9, 20 | crh: &mut gpio::Cr<'B', true>, 21 | ) -> OLED>, PB9>> { 22 | // 将引脚配置为作为开漏输出模式 23 | // scl(时钟线):用于同步数据传输,控制数据的传输速度和顺序。 24 | // 在OLED显示屏中,scl 信号用于同步数据位的发送和接收。 25 | // sda(数据线):用于传输数据到OLED显示屏。 26 | // 在OLED显示屏中,sda 信号用于传输每个像素的数据,包括颜色信息、亮度等。 27 | let mut scl = pb8.into_open_drain_output(crh); 28 | let mut sda = pb9.into_open_drain_output(crh); 29 | scl.set_speed(crh, IOPinSpeed::Mhz50); 30 | sda.set_speed(crh, IOPinSpeed::Mhz50); 31 | 32 | OLED::new(scl, sda) 33 | } 34 | -------------------------------------------------------------------------------- /core/hardware/src/syst/delay.rs: -------------------------------------------------------------------------------- 1 | //! 延时工具库 2 | 3 | use stm32f1xx_hal::flash; 4 | use stm32f1xx_hal::rcc; 5 | use stm32f1xx_hal::timer::{SysDelay, SysTimerExt}; 6 | 7 | /// 封装具有自定义精度的阻塞延迟函数 8 | pub fn sys_delay( 9 | flash: &mut flash::Parts, 10 | rcc: rcc::Rcc, 11 | syst: cortex_m::peripheral::SYST, 12 | ) -> SysDelay { 13 | // 冻结系统中所有时钟的配置,并将冻结的频率存储在时钟中 14 | let clocks = rcc.cfgr.freeze(&mut flash.acr); 15 | 16 | // 具有自定义精度的阻塞延迟 17 | syst.delay(&clocks) 18 | } 19 | -------------------------------------------------------------------------------- /core/hardware/src/syst/mod.rs: -------------------------------------------------------------------------------- 1 | //!系统工具库 2 | 3 | pub mod delay; 4 | 5 | pub use delay::*; 6 | -------------------------------------------------------------------------------- /core/hardware/src/w25q64/conf.rs: -------------------------------------------------------------------------------- 1 | //! 配置 2 | //! 定义W25Q64芯片的相关命令和参数 3 | 4 | // 写使能命令 5 | pub const W25Q64_WRITE_ENABLE: u8 = 0x06; 6 | // 写禁止命令 7 | pub const W25Q64_WRITE_DISABLE: u8 = 0x04; 8 | // 读状态寄存器1命令 9 | pub const W25Q64_READ_STATUS_REGISTER_1: u8 = 0x05; 10 | pub const W25Q64_READ_STATUS_REGISTER_2: u8 = 0x35; 11 | pub const W25Q64_WRITE_STATUS_REGISTER: u8 = 0x01; 12 | // 页编程命令 13 | pub const W25Q64_PAGE_PROGRAM: u8 = 0x02; 14 | pub const W25Q64_QUAD_PAGE_PROGRAM: u8 = 0x32; 15 | // 块擦除命令 16 | pub const W25Q64_BLOCK_ERASE_64KB: u8 = 0xD8; 17 | pub const W25Q64_BLOCK_ERASE_32KB: u8 = 0x52; 18 | // 扇区擦除命令 19 | pub const W25Q64_SECTOR_ERASE_4KB: u8 = 0x20; 20 | pub const W25Q64_CHIP_ERASE: u8 = 0xC7; 21 | pub const W25Q64_ERASE_SUSPEND: u8 = 0x75; 22 | pub const W25Q64_ERASE_RESUME: u8 = 0x7A; 23 | pub const W25Q64_POWER_DOWN: u8 = 0xB9; 24 | pub const W25Q64_HIGH_PERFORMANCE_MODE: u8 = 0xA3; 25 | pub const W25Q64_CONTINUOUS_READ_MODE_RESET: u8 = 0xFF; 26 | pub const W25Q64_RELEASE_POWER_DOWN_HPM_DEVICE_ID: u8 = 0xAB; 27 | // 读取芯片的制造商和设备ID 28 | pub const W25Q64_MANUFACTURER_DEVICE_ID: u8 = 0x90; 29 | pub const W25Q64_READ_UNIQUE_ID: u8 = 0x4B; 30 | // 读取芯片的JEDEC设备ID 31 | pub const W25Q64_JEDEC_DEVICE_ID: u8 = 0x9F; 32 | // 读数据命令 33 | pub const W25Q64_READ_DATA: u8 = 0x03; 34 | pub const W25Q64_FAST_READ: u8 = 0x0B; 35 | pub const W25Q64_FAST_READ_DUAL_OUTPUT: u8 = 0x3B; 36 | pub const W25Q64_FAST_READ_DUAL_IO: u8 = 0xBB; 37 | pub const W25Q64_FAST_READ_QUAD_OUTPUT: u8 = 0x6B; 38 | pub const W25Q64_FAST_READ_QUAD_IO: u8 = 0xEB; 39 | pub const W25Q64_OCTAL_WORD_READ_QUAD_IO: u8 = 0xE3; 40 | 41 | pub const W25Q64_DUMMY_BYTE: u8 = 0xFF; 42 | 43 | // 页大小为256字节 44 | pub const W25Q64_PAGE_SIZE: usize = 256; 45 | -------------------------------------------------------------------------------- /core/hardware/src/w25q64/mod.rs: -------------------------------------------------------------------------------- 1 | //! SPI 读写 W25Q64 非易失性存储器 2 | pub mod conf; 3 | pub mod w25q64_hal; 4 | pub mod w25q64_reg; 5 | -------------------------------------------------------------------------------- /core/stm32f10x_rs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stm32f10x_rs" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | name = "stm32f10x_rs" 8 | path = "src/lib.rs" 9 | harness = false 10 | crate-type = ["staticlib", "rlib"] 11 | 12 | 13 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 14 | [dependencies] 15 | panic-probe = {version = "0.3.1", features = ["print-defmt"]} 16 | 17 | [build-dependencies] 18 | bindgen = "0.66.1" 19 | cc = "1.0.83" 20 | glob = "0.3.1" 21 | -------------------------------------------------------------------------------- /core/stm32f10x_rs/README.md: -------------------------------------------------------------------------------- 1 | # stm32f10x Rust 绑定 2 | 3 | 这是一个 C 语言的 stm32f10x 使用 Rust FFI 绑定的库。 4 | 5 | ## stm32f10x C 语言目录说明 6 | 7 | - stm32f10x: C 程序目录; 8 | - Library: 库函数文件; 9 | - Start: 启动文件; 10 | - System: 常用函数库; 11 | - Conf: 配置包含关系和中断函数; 12 | 13 | ## 编译 14 | 15 | 绑定是动态生成。 16 | 17 | ```shell 18 | cargo build --target thumbv7m-none-eabi --package stm32f10x_rs 19 | ``` 20 | 21 | ## 测试 22 | 23 | ```shell 24 | cargo test --target thumbv7m-none-eabi -p stm32f10x_rs 25 | ``` 26 | -------------------------------------------------------------------------------- /core/stm32f10x_rs/build.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | 3 | use bindgen::{CargoCallbacks, EnumVariation}; 4 | 5 | fn main() { 6 | // 编译文件 7 | let files = [ 8 | "stm32f10x/Library/stm32f10x_rcc.c", 9 | "stm32f10x/Library/stm32f10x_gpio.c", 10 | "stm32f10x/System/delay.c", 11 | ]; 12 | 13 | // 包含路径 14 | let includes = [ 15 | "stm32f10x/Start", 16 | "stm32f10x/Library", 17 | "stm32f10x/System", 18 | "stm32f10x/Conf", 19 | ]; 20 | let gen_includes = [ 21 | "-Istm32f10x/Start", 22 | "-Istm32f10x/Library", 23 | "-Istm32f10x/System", 24 | "-Istm32f10x/Conf", 25 | ]; 26 | let gen_defines = ["-DUSE_STDPERIPH_DRIVER", "-DSTM32F10X_MD"]; 27 | 28 | cc::Build::new() 29 | .includes(&includes) 30 | // .flag("-ffreestanding") 31 | // .files(glob::glob("hello/*.c").unwrap().filter_map(Result::ok)) 32 | .files(&files) 33 | .define("USE_STDPERIPH_DRIVER", None) 34 | .define("STM32F10X_MD", None) 35 | // .target("thumbv7m-none-eabi") 36 | .cargo_metadata(true) 37 | // 运行编译器,生成output文件 38 | .compile("stm32f10x_rs"); 39 | 40 | let bindings = bindgen::Builder::default() 41 | .header("stm32f10x/Conf/stm32f10x_conf.h") 42 | .header("stm32f10x/Start/stm32f10x.h") 43 | .header("stm32f10x/System/delay.h") 44 | // 常量 45 | // .constified_enum("RCC_APB2Periph") 46 | // 枚举 47 | .bitfield_enum("FunctionalState") 48 | .generate_comments(true) 49 | .use_core() 50 | .default_enum_style(EnumVariation::Rust { 51 | non_exhaustive: true, 52 | }) 53 | .parse_callbacks(Box::new(CargoCallbacks)) 54 | .clang_args(gen_includes) 55 | .clang_args(gen_defines) 56 | .generate() 57 | .expect("Unable to generate bindings"); 58 | 59 | // 将绑定写入 bindings.rs 文件。 60 | let out_path = PathBuf::from("./src"); 61 | bindings 62 | .write_to_file(out_path.join("bindings.rs")) 63 | .expect("Couldn't write bindings!"); 64 | } 65 | -------------------------------------------------------------------------------- /core/stm32f10x_rs/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![allow(non_upper_case_globals)] 4 | #![allow(non_camel_case_types)] 5 | #![allow(non_snake_case)] 6 | 7 | use panic_probe as _; 8 | 9 | include!(concat!("./bindings.rs")); 10 | -------------------------------------------------------------------------------- /core/stm32f10x_rs/stm32f10x/Conf/stm32f10x_it.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file Project/STM32F10x_StdPeriph_Template/stm32f10x_it.h 4 | * @author MCD Application Team 5 | * @version V3.5.0 6 | * @date 08-April-2011 7 | * @brief This file contains the headers of the interrupt handlers. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 12 | * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 13 | * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY 14 | * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 15 | * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 16 | * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 17 | * 18 | *

© COPYRIGHT 2011 STMicroelectronics

19 | ****************************************************************************** 20 | */ 21 | 22 | /* Define to prevent recursive inclusion -------------------------------------*/ 23 | #ifndef __STM32F10x_IT_H 24 | #define __STM32F10x_IT_H 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | /* Includes ------------------------------------------------------------------*/ 31 | #include "stm32f10x.h" 32 | 33 | /* Exported types ------------------------------------------------------------*/ 34 | /* Exported constants --------------------------------------------------------*/ 35 | /* Exported macro ------------------------------------------------------------*/ 36 | /* Exported functions ------------------------------------------------------- */ 37 | 38 | void NMI_Handler(void); 39 | void HardFault_Handler(void); 40 | void MemManage_Handler(void); 41 | void BusFault_Handler(void); 42 | void UsageFault_Handler(void); 43 | void SVC_Handler(void); 44 | void DebugMon_Handler(void); 45 | void PendSV_Handler(void); 46 | void SysTick_Handler(void); 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif /* __STM32F10x_IT_H */ 53 | 54 | /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 55 | -------------------------------------------------------------------------------- /core/stm32f10x_rs/stm32f10x/Library/stm32f10x_flash.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/core/stm32f10x_rs/stm32f10x/Library/stm32f10x_flash.c -------------------------------------------------------------------------------- /core/stm32f10x_rs/stm32f10x/Library/stm32f10x_i2c.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/core/stm32f10x_rs/stm32f10x/Library/stm32f10x_i2c.c -------------------------------------------------------------------------------- /core/stm32f10x_rs/stm32f10x/Library/stm32f10x_usart.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/core/stm32f10x_rs/stm32f10x/Library/stm32f10x_usart.c -------------------------------------------------------------------------------- /core/stm32f10x_rs/stm32f10x/Start/stm32f10x.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/core/stm32f10x_rs/stm32f10x/Start/stm32f10x.h -------------------------------------------------------------------------------- /core/stm32f10x_rs/stm32f10x/System/delay.c: -------------------------------------------------------------------------------- 1 | #include "stm32f10x.h" 2 | 3 | 4 | /** 5 | * @brief 微秒级延时 6 | * @param xus 延时时长,范围:0~233015 7 | * @retval 无 8 | */ 9 | void Delay_us(uint32_t xus) 10 | { 11 | // SysTick->LOAD = 72 * xus; //设置定时器重装值 12 | SysTick->LOAD = xus; //设置定时器重装值, 转换rust后的延时 13 | SysTick->VAL = 0x00; //清空当前计数值 14 | SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器 15 | while(!(SysTick->CTRL & 0x00010000)); //等待计数到0 16 | SysTick->CTRL = 0x00000004; //关闭定时器 17 | } 18 | 19 | /** 20 | * @brief 毫秒级延时 21 | * @param xms 延时时长,范围:0~4294967295 22 | * @retval 无 23 | */ 24 | void Delay_ms(uint32_t xms) 25 | { 26 | while(xms--) 27 | { 28 | Delay_us(1000); 29 | } 30 | } 31 | 32 | /** 33 | * @brief 秒级延时 34 | * @param xs 延时时长,范围:0~4294967295 35 | * @retval 无 36 | */ 37 | void Delay_s(uint32_t xs) 38 | { 39 | while(xs--) 40 | { 41 | Delay_ms(1000); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /core/stm32f10x_rs/stm32f10x/System/delay.h: -------------------------------------------------------------------------------- 1 | #ifndef __DELAY_H 2 | #define __DELAY_H 3 | 4 | void Delay_us(uint32_t us); 5 | void Delay_ms(uint32_t ms); 6 | void Delay_s(uint32_t s); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /docs/AI协助.md: -------------------------------------------------------------------------------- 1 | # AI 协助 2 | 3 | ## 提供示例 4 | 5 | ```text 6 | 我希望你担任 Rust 编程语言嵌入式开发专家。指引我使用 stm32f1xx-hal="0.10.0" crate 嵌入式框架进行开发学习,请确保给出的示例的正确性。 7 | 请提供一个读写W25Q64芯片的示例,请确保给出的示例的正确性。 8 | ``` 9 | 10 | ## 提供示例 11 | 12 | ``` 13 | 我希望你担任 Rust 编程语言嵌入式开发专家。指引我使用 stm32f1xx-hal="0.10.0" 嵌入式框架进行开发学习。 14 | 请提供一个W25Q64的示例,并确保正确。 15 | ``` 16 | 17 | ## 修复错误 18 | 19 | ``` 20 | 我希望你担任 Rust 编程语言嵌入式开发专家。指引我使用 stm32f1xx-hal="0.10.0" 嵌入式框架进行开发学习,请确保给出的示例的正确性。 21 | 请帮我分析下面代码有什么问题,设置的窗口时间为30-50ms,然而在 println!("delay..") 位置的就已经重置了. 22 | ``` 23 | 24 | ## 代码转换 25 | 26 | ``` 27 | 我希望你担任 Rust 编程语言嵌入式开发专家。指引我使用 stm32f1xx-hal="0.10.0" 嵌入式框架进行开发学习,请确保给出的示例的正确性。 28 | 以下C语言嵌入式代码转换为Rust语言stm32f1xx-ha对应的代码,并确保正确。 29 | /*SPI使能*/ 30 | SPI_Cmd(SPI1, ENABLE); //使能SPI1,开始运行 31 | ``` 32 | 33 | ## 细节示例 34 | 35 | ``` 36 | 我希望你担任 Rust 编程语言嵌入式开发专家。指引我使用 stm32f1xx-hal="0.10.0" 嵌入式框架进行开发学习,请确保给出的示例的正确性。 37 | 以下是RTC 告警中断的示例,请帮我补充todo信息,并确保正确。 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/Archlinux环境搭建.md: -------------------------------------------------------------------------------- 1 | # 环境搭建 2 | 3 | ## 系统环境 4 | 5 | - 系统版本: Archlinux 6 | - Rust 版本: 1.71.0 7 | - Cargo 版本: 1.71.0 8 | - Rustup 版本: 1.26.0 9 | 10 | ## 安装工具链 11 | 12 | 工具链简介: 13 | 14 | - thumbv6m-none-eabi,适用于 Cortex-M0 和 Cortex-M1 处理器 15 | - thumbv7m-none-eabi,适用于 Cortex-M3 处理器 16 | - thumbv7em-none-eabi,适用于 Cortex-M4 和 Cortex-M 处理器 17 | - thumbv7em-none-eabihf,适用于 Cortex-M4F 和 Cortex-M7F 处理器 18 | - thumbv8m.main-none-eabi,适用于 Cortex-M33 和 Cortex-M35P 处理器 19 | - thumbv8m.main-none-eabihf,适用于 Cortex-M33F 和 Cortex-M35PF 处理器 20 | 21 | ```shell 22 | rustup target add thumbv7m-none-eabi 23 | ``` 24 | 25 | ## 安装 cargo-binutils 26 | 27 | ```shell 28 | rustup component add llvm-tools-preview 29 | 30 | # 安装指定版本 31 | # cargo install cargo-binutils --vers 0.3.3 32 | # 安装最新版本 33 | cargo install cargo-binutils 34 | 35 | cargo size --version 36 | ``` 37 | 38 | ## 安装 cargo-embed 39 | 40 | ```shell 41 | cargo install cargo-embed 42 | 43 | cargo embed --version 44 | ``` 45 | 46 | ## 安装 ARM GCC 编译环境 47 | 48 | ```shell 49 | sudo pacman -S arm-none-eabi-gcc arm-none-eabi-newlib 50 | ``` 51 | 52 | ## 有 ARM 支持的 GDB 53 | 54 | 有 ARM 仿真支持的 QEMU 用于调试 ARM Cortex-M 程序的 GDB 命令 55 | 56 | ```shell 57 | sudo pacman -S arm-none-eabi-gdb 58 | ``` 59 | 60 | ## 终端串口工具 61 | 62 | ```shell 63 | sudo pacman -S minicom 64 | ``` 65 | 66 | ## 图形化串口工具(可选) 67 | 68 | ```shell 69 | yay -S aur/cutecom 70 | ``` 71 | 72 | ## Openocd 调试器 73 | 74 | ```shell 75 | sudo pacman -S openocd 76 | ``` 77 | 78 | ## 仿真模拟器 79 | 80 | ### renode 模拟器(推荐) 81 | 82 | #### 安装 83 | 84 | ``` 85 | wget https://github.com/renode/renode/releases/download/v1.14.0/renode-1.14.0-1-x86_64.pkg.tar.xz 86 | 87 | sudo pacman -U ./renode-1.14.0-1-x86_64.pkg.tar.xz 88 | 89 | renode -v 90 | ``` 91 | 92 | ### 有 ARM 仿真支持的 QEMU 93 | 94 | 使用该模拟器需要安装 stm32 的插件 95 | 96 | #### 安装 97 | 98 | - 默认不支持 stm32 99 | 100 | ```shell 101 | sudo pacman -S qemu-system-arm 102 | ``` 103 | 104 | #### 运行 105 | 106 | 这个程序将会阻塞住。 107 | 108 | ```shell 109 | qemu-system-arm \ 110 | -cpu cortex-m3 \ 111 | -machine lm3s6965evb \ 112 | -gdb tcp::3333 \ 113 | -S \ 114 | -nographic \ 115 | -kernel target/thumbv7m-none-eabi/debug/blinky 116 | ``` 117 | -------------------------------------------------------------------------------- /docs/BluePillPinout.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/docs/BluePillPinout.jpg -------------------------------------------------------------------------------- /docs/Defmt 单元测试.md: -------------------------------------------------------------------------------- 1 | # Defmt 单元测试 2 | 3 | ## 安装依赖 4 | 5 | - flip-link: 6 | 7 | ```shell 8 | cargo install flip-link 9 | ``` 10 | 11 | - probe-run: 12 | 13 | ```shell 14 | # make sure to install v0.2.0 or later 15 | cargo install probe-run 16 | ``` 17 | 18 | - cargo-generate(可选): 19 | 20 | ```shell 21 | cargo install cargo-generate 22 | ``` 23 | 24 | ## 运行测试 25 | 26 | - 运行这些单元测试 27 | 28 | ```shell 29 | cargo test --lib 30 | 31 | cargo test --target thumbv7m-none-eabi -p testsuite 32 | 33 | cargo test --target thumbv7m-none-eabi -p testsuite probe-run -- --chip STM32F103C8 34 | ``` 35 | 36 | - 集成测试 37 | > 集成测试驻留在该 tests 目录中; 38 | > 最初的一组集成测试位于 tests/integration.rs. 39 | > cargo test --test integration 将运行这些集成测试。 40 | > 请注意,标志的参数--test 必须与目录中测试文件的名称匹配 tests。 41 | 42 | ```shell 43 | cargo test --test integration 44 | ``` 45 | 46 | ## 设备调试 47 | 48 | ```shell 49 | # 完整指令 50 | cargo run --target thumbv7m-none-eabi -p testsuite_replace_embed probe-run -- --chip STM32F103C8 trace 51 | 52 | # 简写, 配置的有 `.cargo/config.toml` 文件 53 | cargo run -p testsuite_replace_embed 54 | # 别名 55 | cargo rp testsuite_replace_embed 56 | 57 | # 日志级别 58 | DEFMT_LOG=trace cargo run -p testsuite_replace_embed 59 | 60 | ``` 61 | 62 | ## 设置日志级别 63 | 64 | ```shell 65 | export DEFMT_LOG=info 66 | 67 | # or 68 | DEFMT_LOG=trace cargo rb levels 69 | ``` 70 | 71 | ## 相关文档 72 | 73 | - [defmt app-template](https://github.com/knurling-rs/app-template) 74 | - [defmt](https://github.com/knurling-rs/defmt) 75 | -------------------------------------------------------------------------------- /docs/Linux st-link配置.md: -------------------------------------------------------------------------------- 1 | # Linux st-link 配置 2 | 3 | ## st-link 与开发板连线 4 | 5 | - 注意连线顺序可能与教程不一样; 6 | 7 | ## udev 8 | 9 | ```shell 10 | git clone https://github.com/stlink-org/stlink 11 | 12 | cd stlink 13 | sudo cp config/udev/rules.d/49-stlinkv2-1.rules /etc/udev/rules.d 14 | 15 | # 重新加载udev规则 16 | sudo udevadm control --reload-rules 17 | ``` 18 | 19 | ## 查看设备是否加载 20 | 21 | ```shell 22 | $ lsusb |grep 'ST-LINK/V2' 23 | 24 | Bus 003 Device 033: ID 0483:3748 STMicroelectronics ST-LINK/V2 25 | ``` 26 | 27 | ## 相关文档 28 | 29 | - [Linux 系统如何安装 ST-Link v2 烧录环境](https://www.yisu.com/zixun/501716.html) 30 | - [linux 下 st-link 开发 STM32](https://codeantenna.com/a/gATpTrEEwz) 31 | - [安装 ST-Link GDBServer](https://blog.51cto.com/zoomdy/5871707) 32 | - [ST-link 驱动下载、安装、配置和升级](https://blog.csdn.net/qq_52158753/article/details/130161426) 33 | -------------------------------------------------------------------------------- /docs/Minicom使用文档.md: -------------------------------------------------------------------------------- 1 | # Minicom 使用文档 2 | 3 | ## 打开工具配置界面 4 | 5 | ```shell 6 | sudo minicom -s 7 | ``` 8 | 9 | ![](../images/minicom/1.minicom主配置页面.png) 10 | 11 | ## 查看串口设备 12 | 13 | - 确认串口 14 | - 插拔一下串口端口,看哪一个是新增的,新增的那个设备大概率就是当前的串口了。 15 | 16 | ```shell 17 | ls /dev/ttyUSB* 18 | ``` 19 | 20 | - 查看这个串口设备输出: 21 | 22 | ```shell 23 | cat /dev/ttyUSB0 24 | ``` 25 | 26 | - 对这个设备输入: 27 | 28 | ```shell 29 | echo test > ttyUSB0 30 | ``` 31 | 32 | ## 选择串口设置 33 | 34 | ![](../images/minicom/2.串口设置页.png) 35 | 36 | - 按键盘“A”输入串口的映射文件名 37 | 38 | ![](../images/minicom/3.串行设备配置.png) 39 | 40 | - 按键盘“E”可以修改波特率 41 | ![](../images/minicom/4.波特率配置.png) 42 | 43 | - 按键盘“F”把硬件流关闭,否则 minicom 可能无法接收键盘输入 44 | 45 | ![](../images/minicom/5.硬件流控制.png) 46 | 47 | ## 保存默认配置 48 | 49 | 保存后选择退出。 50 | ![](../images/minicom/6.保存为默认设置.png) 51 | 52 | ## 直接编辑配置文件配置 53 | 54 | - 打开编辑文件 55 | 56 | ```shell 57 | sudo vim /etc/minirc.dfl 58 | ``` 59 | 60 | - 输入以下内容 61 | 62 | ```shell 63 | # 电脑产生的文件 - 使用“minicom -s”以变更参数。 64 | pu port /dev/ttyUSB0 65 | pu baudrate 9600 66 | pu bits 8 67 | pu parity N 68 | pu stopbits 1 69 | pu rtscts No 70 | ``` 71 | 72 | ## 打开串口 73 | 74 | ```shell 75 | sudo minicom 76 | 77 | # 指定编码打开 78 | sudo minicom -R utf8 79 | ``` 80 | 81 | ![](../images/minicom/7.打开串口.png) 82 | 83 | ## 常用指令 84 | 85 | - 退出 minicom:crtl+A->x 86 | - 在 minicom 中打开配置页面:crtl+A->o 87 | - 在 minicom 中输入回车和换行: 88 | - 键入 ctrl+M,即可输入 0D 回车符(\r) 89 | - 键入 ctrl+J,即可输入 0A 换行符(\n) 90 | - 快速打开串口:minicom -D /dev/ttyUSB0 91 | -------------------------------------------------------------------------------- /docs/Openocd使用指南.md: -------------------------------------------------------------------------------- 1 | # Openocd 使用指南 2 | 3 | ## 用户配置文件 4 | 5 | linux 中配置文件一般所在目录 `/usr/share/openocd/scripts` 6 | 7 | 三种主要类型的非用户配置文件: 8 | 9 | - interface: 接口配置文件; 10 | - board: 特定于电路板的,它设置 JTAG TAPS 和 他们的 GDB 目标(通过推迟到某个文件),声明所有闪存;; 11 | - target: 集成 CPU 和其他 JTAG TAPS 的芯片 12 | 13 | 适合当前开发板的配置文件: 14 | 15 | - board: /usr/share/openocd/scripts/board/stm32f103c8_blue_pill.cfg 16 | - target: /usr/share/openocd/scripts/target/stm32f1x.cfg 17 | 18 | ## 配置 19 | 20 | ```text 21 | # 使用CMSIS-DAP协议进行SWD调试 22 | # source [find interface/cmsis-dap.cfg] 23 | 24 | # stlink 25 | source [find interface/stlink.cfg] 26 | # source [find interface/stlink-v2.cfg] 27 | 28 | 29 | # 目标设备芯片类型和调试速率 30 | set TARGET_NAME "cortex_m" 31 | set CHIPNAME "stm32f103c8" 32 | 33 | # clock speed 1000 kHz 34 | # adapter speed 1000 35 | 36 | # 目标设备连接方式和接口编号 37 | transport select hla_swd 38 | # set CONNECT_MODE smp 39 | # set CONNECT_TYPE hla_swd 40 | # hla_layout stlink 41 | # hla_port 4242 42 | 43 | # 选择目标设备 44 | source [find target/stm32f1x.cfg] 45 | ``` 46 | 47 | ## 连接目标设备 48 | 49 | ```shell 50 | openocd -f openocd.cfg 51 | ``` 52 | 53 | ## 参考文档 54 | 55 | - [openocd 调试使用指南](https://www.python100.com/html/5F3U4P5L64PA.html) 56 | - [STM32F3DISCOVERY openocd 调试](https://xxchang.github.io/book/start/hardware.html) 57 | -------------------------------------------------------------------------------- /docs/Renode仿真模拟.md: -------------------------------------------------------------------------------- 1 | # Renode 仿真模拟 2 | 3 | ## 仿真配置文件 4 | 5 | ```shell 6 | # @scripts/stm32f103.resc 7 | cat stm32f103.resc 8 | ``` 9 | 10 | ## 修改默认启动仿真程序 11 | 12 | ```shell 13 | # 修改该行目标程序位置 14 | $bin=@target/thumbv7m-none-eabi/debug/hello 15 | ``` 16 | 17 | ## 启动 Renode CLI 18 | 19 | 打开终端,切换至项目根目录; 20 | 启动 Renode CLI 后会打开一个新的终端窗口; 21 | 22 | ```shell 23 | renode 24 | ``` 25 | 26 | ## 启动 STM32 仿真器 27 | 28 | ```shell 29 | start @scripts/stm32f103.resc 30 | ``` 31 | 32 | ## Renode 在 GDB 连接后立即启动整个模拟。 33 | 34 | ```shell 35 | machine StartGdbServer 3333 true 36 | ``` 37 | 38 | ## GDB 连接 Renode 39 | 40 | ```shell 41 | # 启动 GDB 42 | # 默认启动 43 | # arm-none-eabi-gdb target/thumbv7m-none-eabi/debug/hello 44 | # 指定当前目录下的.gdbinit配置文件启动 45 | arm-none-eabi-gdb -iex 'add-auto-load-safe-path .' -q target/thumbv7m-none-eabi/debug/blinky 46 | 47 | # 连接 Renode 48 | target remote :3333 49 | ``` 50 | 51 | ## 重启仿真器 52 | 53 | ```shell 54 | machine Reset 55 | ``` 56 | 57 | ## 清除仿真程序 58 | 59 | ```shel 60 | Clear 61 | ``` 62 | 63 | ## 查看所有外设 64 | 65 | ```shell 66 | peripherals 67 | ``` 68 | 69 | ## 系统总线挂钩 70 | 71 | - 在访问特定外设进行读取后执行 Python 脚本 72 | 73 | ```shell 74 | (machine) sysbus SetHookAfterPeripheralRead gpioPortA "print '%s peripheral has been accessed to read'" 75 | ``` 76 | 77 | - 在访问特定外围设备进行写入之前执行 Python 脚本 78 | 79 | ```shell 80 | (machine) sysbus SetHookBeforePeripheralWrite peripheral "print '%s peripheral has been accessed to write'" 81 | 82 | ``` 83 | 84 | ## 参考文档 85 | 86 | [renode 指南](https://renode.readthedocs.io/en/latest/introduction/installing.html) 87 | [renode 代码仓库](https://github.com/renode/renode) 88 | [在 Renode 中使用 Python](https://renode.readthedocs.io/en/latest/basic/using-python.html) 89 | [Renode 开启 GDB 调试](https://renode.readthedocs.io/en/latest/debugging/gdb.html) 90 | [使用 GDB 进行调](https://jzow.github.io/discovery/microbit/05-led-roulette/debug-it.html) 91 | -------------------------------------------------------------------------------- /docs/嵌入式入门路线.md: -------------------------------------------------------------------------------- 1 | # 嵌入式入门路线 2 | 3 | ## 学什么 4 | 5 | 部分单片机,部分数据结构,部分实时操作系统 6 | 7 | ## 怎么学 8 | 9 | 1. stm32,去某宝买块带视频教程的开发版,满足去写必学驱动(rcc 时钟系统,定时器,外部中断,i2c,uart 串口,spi,adc,基于定时器的 pwm,可选项:以太网,网络协议占比例如 lwip)就行了,写驱动用标准库或者 ll 库,不要用 hal 库,不要使用 stm32cube(以太网、lwip 除外)。 10 | 底层逻辑需要会独立编码,操作寄存器进行开发驱动,深入理解协议的原理。 11 | 12 | 2. 写驱动过程中了解基础电路知识,知道高低电平,看懂通讯协议,时序图,看懂基本原理图,知道信号怎么走,不要想着硬啃数电,模电。(fpga)用 c 学编程代码。 13 | 14 | 3. 数据结构一定学,挑着学:堆栈,队列,链表,经学,数图表简单了解概念。 15 | 16 | 4. 移植一个实时操作系统的微内核,推荐:ucos RTX FreeRtos,或者国产 RTthread,结合之前写的裸机驱动代码,在上面写几个任务,把任务优先级兼通讯,临界资源保护用起来。 17 | -------------------------------------------------------------------------------- /docs/待学习案例.txt: -------------------------------------------------------------------------------- 1 | hello.rs 2 | led.rs 3 | blinky.rs 4 | blinky_generic.rs 5 | delay.rs 6 | delay-timer-blinky.rs 7 | exti.rs 8 | pwm.rs 9 | pwm_custom.rs 10 | panics.rs 11 | gpio_input.rs 12 | nojtag.rs 13 | pwm_input.rs 14 | qei.rs 15 | adc-dma-rx.rs 16 | adc.rs 17 | adc-dma-circ.rs 18 | adc_temperature.rs 19 | serial_config.rs 20 | serial.rs 21 | serial_reconfigure.rs 22 | serial-fmt.rs 23 | serial-interrupt-idle.rs 24 | serial_9bits.rs 25 | multi_mode_gpio.rs 26 | dynamic_gpio.rs 27 | timer-interrupt-rtic.rs 28 | exti_rtic.rs 29 | blinky_timer_irq.rs 30 | mpu9250.rs.disabled 31 | blinky_rtc.rs 32 | rtc.rs 33 | blinky_rtcalarm_irq.rs 34 | 35 | 36 | spi-dma.rs 37 | spi-slave.rs 38 | spi.rs 39 | serial-dma-circ.rs 40 | serial-dma-peek.rs 41 | serial-dma-rx.rs 42 | serial-dma-tx.rs 43 | 44 | 45 | i2c-bme280 46 | can-echo.rs 47 | can-loopback.rs 48 | can-rtic.rs 49 | crc.rs 50 | enc28j60-coap.rs.disabled 51 | enc28j60.rs.disabled 52 | itm.rs 53 | mfrc522.rs 54 | motor.rs.disabled 55 | usb_serial.rs 56 | usb_serial_interrupt.rs 57 | usb_serial_rtic.rs 58 | -------------------------------------------------------------------------------- /docs/术语介绍.md: -------------------------------------------------------------------------------- 1 | # 术语介绍 2 | 3 | ## stm32f1xx_hal 库 4 | 5 | stm32f1xx_hal 是一个硬件抽象层(HAL)库,它为 STM32F1 系列微控制器提供了一组 Rust 接口。 6 | 这些接口抽象了底层硬件的细节,使得开发者可以更高效地编写代码。 7 | 8 | ## cortex_m_rt 库 9 | 10 | cortex_m_rt 是一个实时操作系统(RTOS)库,它提供了一些用于在 Cortex-M 处理器上运行实时任务的基础设施。 11 | cortex_m_rt 的主要作用是提供一种方式来定义和管理实时任务。 12 | 它还提供了一些用于处理中断和异常的工具。 13 | 这个库主要用于在 Cortex-M 处理器上运行的程序,如果你的嵌入式系统使用的是 Cortex-M 处理器,那么你可以使用这个库。 14 | 15 | ## STM32F1 的复位模块 16 | 17 | 复位功能可以重启微控制器,恢复到初始状态。 18 | 19 | ## STM32F1 的时钟控制(RCC) 20 | 21 | STM32F1 的时钟控制(RCC)模块负责管理微控制器的时钟。 22 | 时钟控制功能可以配置微控制器的时钟源和时钟频率,这对于定时器和其他需要时钟的外设来说非常重要。 23 | 24 | ## 外设 25 | 26 | "Cortex-M 核心的外设"和"STM32F1 的外设"是两个不同级别的硬件资源。 27 | Cortex-M 核心的外设是所有使用 Cortex-M 处理器的设备都有的,比如系统定时器。 28 | STM32F1 的外设是 STM32F1 微控制器特有的,比如 GPIO 端口和 RCC 模块。 29 | 这两者需要分开引入,因为它们属于不同的硬件级别。 30 | 31 | ## FLASH 控制器 32 | 33 | FLASH 控制器用于管理微控制器的 FLASH 存储器。 34 | 将 FLASH 控制器放入受限状态是为了防止在配置过程中发生错误,比如在 FLASH 写入过程中意外地改变了其他设置。 35 | 36 | ## GPIOC 37 | 38 | PIOC 是 STM32F1 微控制器的一个 GPIO(General Purpose Input/Output,通用输入输出)端口。STM32F1 有多个 GPIO 端口,每个端口有多个引脚,可以配置为输入或输出。 39 | 40 | ## 推挽输出 41 | 42 | "推挽输出"是一种电路配置,它可以使引脚输出高电平或低电平。当配置为推挽输出时,引脚可以被驱动为高电平(通过将引脚连接到电源),或者低电平(通过将引脚连接到地)。 43 | 44 | ## Hz(赫兹) 45 | 46 | Hz(赫兹)是频率的单位,1Hz 表示每秒钟发生一次。所以,如果定时器的频率为 1Hz,那么它每秒钟会产生一次中断。如果你想让定时器每 500 毫秒产生一次中断,那么你应该将定时器的频率设置为 2Hz。 47 | -------------------------------------------------------------------------------- /images/BluePillPinout.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/BluePillPinout.jpg -------------------------------------------------------------------------------- /images/minicom/1.minicom主配置页面.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/minicom/1.minicom主配置页面.png -------------------------------------------------------------------------------- /images/minicom/2.串口设置页.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/minicom/2.串口设置页.png -------------------------------------------------------------------------------- /images/minicom/3.串行设备配置.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/minicom/3.串行设备配置.png -------------------------------------------------------------------------------- /images/minicom/4.波特率配置.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/minicom/4.波特率配置.png -------------------------------------------------------------------------------- /images/minicom/5.硬件流控制.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/minicom/5.硬件流控制.png -------------------------------------------------------------------------------- /images/minicom/6.保存为默认设置.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/minicom/6.保存为默认设置.png -------------------------------------------------------------------------------- /images/minicom/7.打开串口.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/minicom/7.打开串口.png -------------------------------------------------------------------------------- /images/wiring_diagram/10-1 软件I2C读写MPU6050.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/10-1 软件I2C读写MPU6050.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/10-2 硬件I2C读写MPU6050.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/10-2 硬件I2C读写MPU6050.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/11-1 模拟SPI读写W25Q64.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/11-1 模拟SPI读写W25Q64.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/11-2 硬件SPI读写W25Q64.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/11-2 硬件SPI读写W25Q64.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/12-1 实时时钟.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/12-1 实时时钟.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/12-2 读写备份寄存器.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/12-2 读写备份寄存器.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/13-1 修改主频.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/13-1 修改主频.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/13-2 睡眠模式+串口发送+接收.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/13-2 睡眠模式+串口发送+接收.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/13-3 停止模式+对射式红外传感器计次.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/13-3 停止模式+对射式红外传感器计次.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/13-4 待机模式+实时时钟.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/13-4 待机模式+实时时钟.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/14-1 独立看门狗.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/14-1 独立看门狗.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/14-2 窗口看门狗.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/14-2 窗口看门狗.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/15-1 读写内部FLASH.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/15-1 读写内部FLASH.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/15-2 读取芯片ID.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/15-2 读取芯片ID.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/2-1 工程模板.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/2-1 工程模板.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/3-1 LED闪烁.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/3-1 LED闪烁.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/3-2 LED流水灯.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/3-2 LED流水灯.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/3-3 蜂鸣器.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/3-3 蜂鸣器.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/3-4 按键控制LED.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/3-4 按键控制LED.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/3-5 光敏传感器控制蜂鸣器.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/3-5 光敏传感器控制蜂鸣器.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/4-1 OLED显示屏.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/4-1 OLED显示屏.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/5-1 对射式红外传感器计次.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/5-1 对射式红外传感器计次.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/5-2 旋转编码器计次.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/5-2 旋转编码器计次.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/6-1 定时器定时中断.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/6-1 定时器定时中断.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/6-2 定时器外部时钟.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/6-2 定时器外部时钟.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/6-3 PWM驱动LED呼吸灯.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/6-3 PWM驱动LED呼吸灯.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/6-4 PWM驱动舵机.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/6-4 PWM驱动舵机.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/6-5 PWM驱动直流电机.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/6-5 PWM驱动直流电机.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/6-7 PWMI模式测频率占空比.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/6-7 PWMI模式测频率占空比.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/6-8 编码器接口测速.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/6-8 编码器接口测速.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/7-1 AD单通道.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/7-1 AD单通道.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/7-2 AD多通道.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/7-2 AD多通道.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/8-1 DMA数据转运.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/8-1 DMA数据转运.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/8-2 DMA+AD多通道.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/8-2 DMA+AD多通道.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/9-1 串口发送.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/9-1 串口发送.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/9-2 串口发送+接收.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/9-2 串口发送+接收.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/9-3 串口收发HEX数据包.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/9-3 串口收发HEX数据包.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/9-4 串口收发文本数据包.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/9-4 串口收发文本数据包.jpg -------------------------------------------------------------------------------- /images/wiring_diagram/NRF24L01引脚图.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silent-rain/stm32f103-tutorial/56da8c1179bf8b688223c70fce8c81bb3b3f84a2/images/wiring_diagram/NRF24L01引脚图.jpg -------------------------------------------------------------------------------- /memory.x: -------------------------------------------------------------------------------- 1 | /* Linker script for the STM32F103C8T6 */ 2 | MEMORY 3 | { 4 | FLASH : ORIGIN = 0x08000000, LENGTH = 64K 5 | RAM : ORIGIN = 0x20000000, LENGTH = 20K 6 | } -------------------------------------------------------------------------------- /openocd.cfg: -------------------------------------------------------------------------------- 1 | # 使用CMSIS-DAP协议进行SWD调试 2 | # source [find interface/cmsis-dap.cfg] 3 | 4 | # stlink 5 | source [find interface/stlink.cfg] 6 | # source [find interface/stlink-v2.cfg] 7 | 8 | 9 | # 目标设备芯片类型和调试速率 10 | set TARGET_NAME "cortex_m" 11 | set CHIPNAME "stm32f103c8" 12 | 13 | # clock speed 1000 kHz 14 | # adapter speed 1000 15 | 16 | # 目标设备连接方式和接口编号 17 | transport select hla_swd 18 | # set CONNECT_MODE smp 19 | # set CONNECT_TYPE hla_swd 20 | # hla_layout stlink 21 | # hla_port 4242 22 | 23 | # 选择目标设备 24 | source [find target/stm32f1x.cfg] 25 | -------------------------------------------------------------------------------- /rust-toolchain: -------------------------------------------------------------------------------- 1 | stable -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 100 2 | hard_tabs = false 3 | tab_spaces = 4 4 | newline_style = "Unix" 5 | use_small_heuristics = "Default" 6 | reorder_imports = true 7 | reorder_modules = true 8 | remove_nested_parens = true 9 | edition = "2021" 10 | # merge_derives = true 11 | use_try_shorthand = false 12 | use_field_init_shorthand = false 13 | force_explicit_abi = true 14 | # normalize_comments = true 15 | normalize_doc_attributes = true 16 | # wrap_comments = true 17 | # imports_granularity = "Crate" 18 | -------------------------------------------------------------------------------- /scripts/stm32f103.resc: -------------------------------------------------------------------------------- 1 | using sysbus 2 | 3 | # Creating machines 4 | mach create 5 | 6 | # 加载 stm32 配置 7 | # machine LoadPlatformDescription @platforms/cpus/stm32f103.repl 8 | machine LoadPlatformDescription @scripts/platforms/cpus/stm32f103.repl 9 | 10 | # 加载平台描述节点 11 | # machine LoadPlatformDescriptionFromString "button: Miscellaneous.Button @ gpioPortC 13 { IRQ -> gpioPortC@13 }" 12 | 13 | 14 | # 指定二进制程序 15 | $bin=@target/thumbv7m-none-eabi/debug/flash_tool_embed 16 | 17 | 18 | # 分析外设 19 | showAnalyzer usart2 20 | 21 | 22 | # 定义 reset 宏 23 | macro reset 24 | """ 25 | sysbus LoadELF $bin 26 | """ 27 | 28 | # 执行 rest 宏 29 | runMacro $reset 30 | 31 | 32 | set gpioa_script """ 33 | print("value: %s, offset: %s" % (value, offset)) 34 | """ 35 | 36 | # 在访问特定外围设备进行写入之前执行 Python 脚本 37 | sysbus SetHookBeforePeripheralWrite gpioPortA $gpioa_script 38 | 39 | 40 | # 开启 GDB 调试 41 | machine StartGdbServer 3333 true 42 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![deny(unsafe_code)] 4 | 5 | use defmt_rtt as _; // global logger 6 | 7 | // adjust HAL import 8 | use stm32f1xx_hal as _; // memory layout 9 | 10 | use panic_probe as _; 11 | 12 | pub fn add(left: usize, right: usize) -> usize { 13 | left + right 14 | } 15 | 16 | // defmt-test 0.3.0 has the limitation that this `#[tests]` attribute can only be used 17 | // once within a crate. the module can be in any file but there can only be at most 18 | // one `#[tests]` module in this library crate 19 | #[cfg(test)] 20 | #[defmt_test::tests] 21 | mod tests { 22 | use super::*; 23 | 24 | use defmt::assert_eq; 25 | 26 | #[test] 27 | fn it_works() { 28 | let result = add(2, 2); 29 | assert_eq!(result, 4); 30 | } 31 | } 32 | --------------------------------------------------------------------------------