|
7 | 7 | //! URL : <https://m-a-h-b-u-b.github.io> |
8 | 8 | //! GitHub : <https://github.com/m-a-h-b-u-b/M2-Bootloader-Rust> |
9 | 9 |
|
10 | | -#![no_std] |
| 10 | +// Build without the Rust standard library—important for embedded targets. |
| 11 | +#![no_std] |
11 | 12 |
|
12 | | -use core::ptr; |
| 13 | +// Provides volatile read/write functions for direct memory access. |
| 14 | +use core::ptr; |
13 | 15 |
|
14 | | -const GPIO_PORT_BASE: u32 = 0x5000_0000; // Replace with your MCU GPIO base |
15 | | -const LED_PIN: u32 = 5; // Example: Pin 5 |
| 16 | +// Hardware-Specific Constants |
| 17 | +const GPIO_PORT_BASE: u32 = 0x5000_0000; // Base address of the MCU's GPIO peripheral. |
| 18 | +// NOTE: Replace this address with the actual GPIO base of your target MCU. |
| 19 | +const LED_PIN: u32 = 5; // LED connected to GPIO pin number 5 (example). |
16 | 20 |
|
17 | | -/// Initialize LED GPIO pin as output |
| 21 | +// LED GPIO Initialization |
| 22 | +// Initialize LED GPIO pin as output |
| 23 | +// |
| 24 | +// This function configures the selected LED pin to act as an output pin |
| 25 | +// by writing to the GPIO port's MODER (Mode Register). |
18 | 26 | pub fn init_led() { |
19 | 27 | unsafe { |
20 | | - // Configure LED_PIN as output |
21 | | - let moder = (GPIO_PORT_BASE + 0x00) as *mut u32; // MODER register |
| 28 | + // Calculate the address of the MODER register. |
| 29 | + let moder = (GPIO_PORT_BASE + 0x00) as *mut u32; |
| 30 | + |
| 31 | + // Read the current MODER value without compiler optimizations |
| 32 | + // to ensure hardware register consistency. |
22 | 33 | let current = ptr::read_volatile(moder); |
23 | | - // Clear previous mode bits and set as output (01) |
| 34 | + |
| 35 | + // Clear the existing 2-bit mode field for LED_PIN, |
| 36 | + // then set it to `01` (binary) for "General Purpose Output Mode". |
24 | 37 | ptr::write_volatile( |
25 | 38 | moder, |
26 | 39 | (current & !(0b11 << (LED_PIN * 2))) | (0b01 << (LED_PIN * 2)), |
27 | 40 | ); |
28 | 41 | } |
29 | 42 | } |
30 | 43 |
|
| 44 | +// ----------------------------------------------------------------------------- |
| 45 | +// LED Control Functions |
| 46 | +// ----------------------------------------------------------------------------- |
| 47 | + |
31 | 48 | /// Turn LED on |
| 49 | +/// |
| 50 | +/// Sets the LED pin's bit in the Output Data Register (ODR) to logic high. |
32 | 51 | pub fn led_on() { |
33 | 52 | unsafe { |
34 | | - let odr = (GPIO_PORT_BASE + 0x14) as *mut u32; // Output Data Register |
| 53 | + let odr = (GPIO_PORT_BASE + 0x14) as *mut u32; // ODR register offset is 0x14. |
| 54 | + // OR the current ODR value with the LED bit to turn it on. |
35 | 55 | ptr::write_volatile(odr, ptr::read_volatile(odr) | (1 << LED_PIN)); |
36 | 56 | } |
37 | 57 | } |
38 | 58 |
|
39 | 59 | /// Turn LED off |
| 60 | +/// |
| 61 | +/// Clears the LED pin's bit in the Output Data Register (ODR) to logic low. |
40 | 62 | pub fn led_off() { |
41 | 63 | unsafe { |
42 | 64 | let odr = (GPIO_PORT_BASE + 0x14) as *mut u32; |
| 65 | + // AND the current ODR value with the inverse of LED bit to turn it off. |
43 | 66 | ptr::write_volatile(odr, ptr::read_volatile(odr) & !(1 << LED_PIN)); |
44 | 67 | } |
45 | 68 | } |
46 | 69 |
|
47 | 70 | /// Toggle LED state |
| 71 | +/// |
| 72 | +/// Flips the current logic level of the LED pin by XORing the ODR value. |
48 | 73 | pub fn toggle_led() { |
49 | 74 | unsafe { |
50 | 75 | let odr = (GPIO_PORT_BASE + 0x14) as *mut u32; |
| 76 | + // XOR toggles the LED bit: if on → off, if off → on. |
51 | 77 | ptr::write_volatile(odr, ptr::read_volatile(odr) ^ (1 << LED_PIN)); |
52 | 78 | } |
53 | 79 | } |
0 commit comments