|
@@ -12,29 +12,134 @@
|
|
|
#define gpio_led gpiob
|
|
|
#define pin_led 13
|
|
|
|
|
|
-static void mcu_board_init(void)
|
|
|
+enum { _A = 0, _B, _C, _D, _E, _F, _G, _H, _I };
|
|
|
+enum { _OD = 0, _PP };
|
|
|
+
|
|
|
+GPIO gpio_from_id(uint8_t id)
|
|
|
{
|
|
|
- uint16_t a = 0x9930; /* PA4-5,8,11-12,15 */
|
|
|
- uint16_t b = 0x23f8; /* PB3-9,13 */
|
|
|
- uint16_t c = 0xffe7; /* PC0-2,5-15 */
|
|
|
- uint16_t d = 0xffff; /* PD0-15 */
|
|
|
- uint16_t e = 0xffff; /* PE0-15 */
|
|
|
- uint16_t f = 0xffff; /* PF0-15 */
|
|
|
- uint16_t g = 0xffff; /* PG0-15 */
|
|
|
- uint16_t h = 0xffff; /* PH0-15 */
|
|
|
- uint16_t i = 0xffff; /* PI0-15 */
|
|
|
- uint32_t ahb1enr = rcc->ahb1enr;
|
|
|
+ switch (id) {
|
|
|
+ case _A: return gpioa;
|
|
|
+ case _B: return gpiob;
|
|
|
+ case _C: return gpioc;
|
|
|
+ case _D: return gpiod;
|
|
|
+ case _E: return gpioe;
|
|
|
+ case _F: return gpiof;
|
|
|
+ case _G: return gpiog;
|
|
|
+ case _H: return gpioh;
|
|
|
+ case _I: return gpioi;
|
|
|
+ }
|
|
|
+ ASSERT(0);
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+const static struct user_pin _user_pins_F7SM_basic[] = {
|
|
|
+ { 2, _B, 12, _OD },
|
|
|
+ { 0, 0, 0, _OD } };
|
|
|
+const static struct user_pin _user_pins_F7SM_ambertronic_f7_plus[] = {
|
|
|
+ { 2, _B, 12, _OD }, /* board bug: B12 isn't buffered */
|
|
|
+ { 4, _C, 6, _PP },
|
|
|
+ { 0, 0, 0, _PP } };
|
|
|
+const static struct user_pin _user_pins_F7SM_lightning[] = {
|
|
|
+ { 2, _B, 12, _PP },
|
|
|
+ { 4, _E, 15, _PP },
|
|
|
+ { 6, _E, 14, _PP },
|
|
|
+ { 0, 0, 0, _PP } };
|
|
|
+const static struct board_config _board_config[] = {
|
|
|
+ [F7SM_basic] = {
|
|
|
+ .hse_mhz = 8,
|
|
|
+ .hs_usb = FALSE,
|
|
|
+ .user_pins = _user_pins_F7SM_basic },
|
|
|
+ [F7SM_ambertronic_f7_plus] = {
|
|
|
+ .hse_mhz = 8,
|
|
|
+ .hs_usb = FALSE,
|
|
|
+ .user_pins = _user_pins_F7SM_ambertronic_f7_plus },
|
|
|
+ [F7SM_lightning] = {
|
|
|
+ .hse_mhz = 16,
|
|
|
+ .hs_usb = TRUE,
|
|
|
+ .user_pins = _user_pins_F7SM_lightning },
|
|
|
+};
|
|
|
+const struct board_config *board_config;
|
|
|
+
|
|
|
+#define early_delay_ms(ms) (delay_ticks((ms)*2000))
|
|
|
+#define early_delay_us(ms) (delay_ticks((ms)*2))
|
|
|
|
|
|
- switch (gw_info.hw_submodel) {
|
|
|
- case F7SM_basic:
|
|
|
- break;
|
|
|
- case F7SM_ambertronic_f7_plus:
|
|
|
- break;
|
|
|
- case F7SM_lightning:
|
|
|
- /* Uses PE12 and PE13 for extra drive outputs. */
|
|
|
- ahb1enr |= RCC_AHB1ENR_GPIOEEN;
|
|
|
- break;
|
|
|
+/* Blink the activity LED to indicate fatal error. */
|
|
|
+static void early_fatal(int blinks) __attribute__((noreturn));
|
|
|
+static void early_fatal(int blinks)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ rcc->ahb1enr |= RCC_AHB1ENR_GPIOBEN;
|
|
|
+ delay_ticks(10);
|
|
|
+ gpio_configure_pin(gpiob, 13, GPO_pushpull(IOSPD_LOW, HIGH));
|
|
|
+ for (;;) {
|
|
|
+ for (i = 0; i < blinks; i++) {
|
|
|
+ gpio_write_pin(gpiob, 13, LOW);
|
|
|
+ early_delay_ms(150);
|
|
|
+ gpio_write_pin(gpiob, 13, HIGH);
|
|
|
+ early_delay_ms(150);
|
|
|
+ }
|
|
|
+ early_delay_ms(2000);
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+void identify_board_config(void)
|
|
|
+{
|
|
|
+ uint16_t low, high;
|
|
|
+ uint8_t id = 0;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ rcc->ahb1enr |= RCC_AHB1ENR_GPIOCEN;
|
|
|
+ early_delay_us(2);
|
|
|
+
|
|
|
+ /* Pull PC[15:13] low, and check which are tied HIGH. */
|
|
|
+ for (i = 0; i < 3; i++)
|
|
|
+ gpio_configure_pin(gpioc, 13+i, GPI_pull_down);
|
|
|
+ early_delay_us(10);
|
|
|
+ high = (gpioc->idr >> 13) & 7;
|
|
|
+
|
|
|
+ /* Pull PC[15:13] high, and check which are tied LOW. */
|
|
|
+ for (i = 0; i < 3; i++)
|
|
|
+ gpio_configure_pin(gpioc, 13+i, GPI_pull_up);
|
|
|
+ early_delay_us(10);
|
|
|
+ low = (~gpioc->idr >> 13) & 7;
|
|
|
+
|
|
|
+ /* Each PCx pin defines a 'trit': 0=float, 1=low, 2=high.
|
|
|
+ * We build a 3^3 ID space from the resulting three-trit ID. */
|
|
|
+ for (i = 0; i < 3; i++) {
|
|
|
+ id *= 3;
|
|
|
+ switch ((high>>1&2) | (low>>2&1)) {
|
|
|
+ case 0: break; /* float = 0 */
|
|
|
+ case 1: id += 1; break; /* LOW = 1 */
|
|
|
+ case 2: id += 2; break; /* HIGH = 2 */
|
|
|
+ case 3: early_fatal(1); /* cannot be tied HIGH *and* LOW! */
|
|
|
+ }
|
|
|
+ high <<= 1;
|
|
|
+ low <<= 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Panic if the ID is unrecognised. */
|
|
|
+ if (id >= ARRAY_SIZE(_board_config))
|
|
|
+ early_fatal(2);
|
|
|
+
|
|
|
+ gw_info.hw_submodel = id;
|
|
|
+ board_config = &_board_config[id];
|
|
|
+}
|
|
|
+
|
|
|
+static void mcu_board_init(void)
|
|
|
+{
|
|
|
+ uint16_t pu[] = {
|
|
|
+ [_A] = 0x9930, /* PA4-5,8,11-12,15 */
|
|
|
+ [_B] = 0x23f8, /* PB3-9,13 */
|
|
|
+ [_C] = 0xffe7, /* PC0-2,5-15 */
|
|
|
+ [_D] = 0xffff, /* PD0-15 */
|
|
|
+ [_E] = 0xffff, /* PE0-15 */
|
|
|
+ [_F] = 0xffff, /* PF0-15 */
|
|
|
+ [_G] = 0xffff, /* PG0-15 */
|
|
|
+ [_H] = 0xffff, /* PH0-15 */
|
|
|
+ [_I] = 0xffff, /* PI0-15 */
|
|
|
+ };
|
|
|
+ uint32_t ahb1enr = rcc->ahb1enr;
|
|
|
+ const struct user_pin *upin;
|
|
|
|
|
|
/* Enable all GPIO bank register clocks to configure unused pins. */
|
|
|
rcc->ahb1enr |= (RCC_AHB1ENR_GPIOAEN |
|
|
@@ -48,15 +153,22 @@ static void mcu_board_init(void)
|
|
|
RCC_AHB1ENR_GPIOIEN);
|
|
|
peripheral_clock_delay();
|
|
|
|
|
|
- gpio_pull_up_pins(gpioa, a);
|
|
|
- gpio_pull_up_pins(gpiob, b);
|
|
|
- gpio_pull_up_pins(gpioc, c);
|
|
|
- gpio_pull_up_pins(gpiod, d);
|
|
|
- gpio_pull_up_pins(gpioe, e);
|
|
|
- gpio_pull_up_pins(gpiof, f);
|
|
|
- gpio_pull_up_pins(gpiog, g);
|
|
|
- gpio_pull_up_pins(gpioh, h);
|
|
|
- gpio_pull_up_pins(gpioi, i);
|
|
|
+ /* Keep clock enabled for all banks containing user-modifiable pins.
|
|
|
+ * Also do not default these pins to pull-up mode. */
|
|
|
+ for (upin = board_config->user_pins; upin->pin_id != 0; upin++) {
|
|
|
+ ahb1enr |= 1u << upin->gpio_bank;
|
|
|
+ pu[upin->gpio_bank] &= ~(1u << upin->gpio_pin);
|
|
|
+ }
|
|
|
+
|
|
|
+ gpio_pull_up_pins(gpioa, pu[_A]);
|
|
|
+ gpio_pull_up_pins(gpiob, pu[_B]);
|
|
|
+ gpio_pull_up_pins(gpioc, pu[_C]);
|
|
|
+ gpio_pull_up_pins(gpiod, pu[_D]);
|
|
|
+ gpio_pull_up_pins(gpioe, pu[_E]);
|
|
|
+ gpio_pull_up_pins(gpiof, pu[_F]);
|
|
|
+ gpio_pull_up_pins(gpiog, pu[_G]);
|
|
|
+ gpio_pull_up_pins(gpioh, pu[_H]);
|
|
|
+ gpio_pull_up_pins(gpioi, pu[_I]);
|
|
|
|
|
|
/* Unused GPIO banks can have their clocks disabled again. They will
|
|
|
* statically hold their configuration state. */
|