|
20 | 20 | //! preserved as separate source here). |
21 | 21 | //! |
22 | 22 | //! Device #2: `cpp/lcd_shim.cpp` bridges the same way to a real 16x2 |
23 | | -//! character LCD over I2C1 (PB6/PB7) via a PCF8574 backpack -- zero new |
24 | | -//! OneIO/OneBus driver code needed (both were already platform-agnostic), |
25 | | -//! one real gap found+fixed in OneChip (a missing single-byte |
26 | | -//! `TwiMaster::send(addr,byte)` overload `oneBus::I2cGpio` needs). Also |
27 | | -//! switches the clock to real 72MHz PLL, not just raw 8MHz HSI -- |
28 | | -//! `hd44780.h`'s portable delay loop is calibrated assuming ~72MHz, and |
29 | | -//! running it at only 8MHz would make every LCD init delay ~9x too |
30 | | -//! short. See README.md for the full story. |
| 23 | +//! character LCD over I2C1 (PB6/PB7) via a PCF8574 backpack, using the |
| 24 | +//! unmodified oneIO::display::I2cLcd -> Hd44780 -> oneBus::I2cGpio -> |
| 25 | +//! hw::stm32::Stm32I2cCore stack -- composition over a real peripheral, |
| 26 | +//! not a toy counter. Needs a PLL clock (hd44780.h's delay loop assumes |
| 27 | +//! ~72MHz; the 8MHz HSI reset default would under-delay LCD init ~9x). |
| 28 | +//! See README.md. |
31 | 29 | #![no_std] |
32 | 30 | #![no_main] |
33 | 31 |
|
@@ -61,27 +59,12 @@ fn main() -> ! { |
61 | 59 | let mut gpioc = dp.GPIOC.split(&mut dp.RCC); |
62 | 60 |
|
63 | 61 | let mut flash = dp.FLASH.constrain(); |
64 | | - // HSI-derived PLL, NOT HSE -- real, sequenced findings, both caught |
65 | | - // by register readback rather than assumed: |
66 | | - // (1) rcc::Config::hsi().sysclk(72.MHz()) does not error on an |
67 | | - // unreachable target -- HSI/2=4MHz's max PLL multiplier is x16 |
68 | | - // (hardware limit), so it silently clamps to 64MHz instead of |
69 | | - // the requested 72MHz (confirmed: PLLSRC=0, PLLMUL=x16). |
70 | | - // (2) Tried rcc::Config::hse(8.MHz()).sysclk(72.MHz()) to reach the |
71 | | - // literal 72MHz via the Blue Pill's onboard crystal -- REVERTED: |
72 | | - // the driver's real HSE-ready wait is an unconditional busy-loop |
73 | | - // (`while hserdy is clear {}`) with no timeout, executed BEFORE |
74 | | - // any PLL/LED/LCD code. If this specific board's HSE crystal |
75 | | - // isn't populated or isn't starting, that hangs forever and |
76 | | - // NOTHING after it (including the LCD output below) ever runs. |
77 | | - // A second register readback after that attempt was consistent |
78 | | - // with exactly this (state frozen before the PLL step), not |
79 | | - // confirmed as a working 72MHz clock. |
80 | | - // 64MHz (not 72MHz) is safe for hd44780.h's delay calibration: a |
81 | | - // slower-than-assumed clock makes the busy-loop delays LONGER than |
82 | | - // the nominal microsecond value, not shorter -- HD44780 tolerates |
83 | | - // longer-than-minimum delays fine, only under-delaying breaks it |
84 | | - // (the real problem the original 8MHz-only config had). |
| 62 | + // sysclk(72.MHz()) on HSI silently clamps to 64 MHz -- HSI/2 = 4 MHz |
| 63 | + // caps the PLL at x16 (PLLSRC=0, PLLMUL=x16, register-confirmed). The |
| 64 | + // HSE path for a literal 72 MHz is avoided: the HAL's HSE-ready wait |
| 65 | + // is an un-timeout'd busy-loop, so a dead crystal hangs the firmware. |
| 66 | + // 64 MHz is fine for hd44780.h -- a slower clock only over-delays. |
| 67 | + // lcd_shim.cpp pins the I2C core to the matching 32 MHz APB1. |
85 | 68 | let _rcc = dp.RCC.freeze(rcc::Config::hsi().sysclk(72.MHz()), &mut flash.acr); |
86 | 69 |
|
87 | 70 | let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh); |
|
0 commit comments