mirror of
https://github.com/keirf/greaseweazle-firmware.git
synced 2025-10-31 11:06:44 -07:00
AT32F4: Identify MCU and board at startup, blink a fail code on error.
Insert required delays for F403 clock bringup. 'gw info' now identifies V4 boards by name.
This commit is contained in:
@@ -10,3 +10,10 @@ extern unsigned int FLASH_PAGE_SIZE;
|
||||
#define AT32F403A 0x07
|
||||
#define AT32F407 0x08
|
||||
extern unsigned int at32f4_series;
|
||||
|
||||
void identify_board_config(void);
|
||||
|
||||
/* On reset, SYSCLK=HSI at 8MHz. SYSCLK runs at 1MHz. */
|
||||
void early_fatal(int blinks) __attribute__((noreturn));
|
||||
#define early_delay_ms(ms) (delay_ticks((ms)*1000))
|
||||
#define early_delay_us(us) (delay_ticks((us)*1))
|
||||
|
||||
@@ -110,6 +110,7 @@ struct board_config {
|
||||
|
||||
void identify_board_config(void);
|
||||
|
||||
/* On reset, SYSCLK=HSI at 16MHz. SYSCLK runs at 2MHz. */
|
||||
void early_fatal(int blinks) __attribute__((noreturn));
|
||||
#define early_delay_ms(ms) (delay_ticks((ms)*2000))
|
||||
#define early_delay_us(us) (delay_ticks((us)*2))
|
||||
|
||||
@@ -17,6 +17,7 @@ from greaseweazle import version
|
||||
|
||||
model_id = { 1: { 0: 'F1',
|
||||
1: 'F1 Plus' },
|
||||
4: { 0: 'V4' },
|
||||
7: { 0: 'F7 v1',
|
||||
1: 'F7 Plus (Ant Goffart, v1)',
|
||||
2: 'F7 Lightning',
|
||||
|
||||
@@ -33,6 +33,68 @@ const static struct board_config _board_config = {
|
||||
.msel_pins = _msel_pins
|
||||
};
|
||||
|
||||
/* Blink the activity LED to indicate fatal error. */
|
||||
void early_fatal(int blinks)
|
||||
{
|
||||
int i;
|
||||
rcc->apb2enr |= RCC_APB2ENR_IOPBEN;
|
||||
delay_ticks(10);
|
||||
gpio_configure_pin(gpio_led, pin_led, 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->apb2enr |= RCC_APB2ENR_IOPCEN;
|
||||
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 != 0)
|
||||
early_fatal(2);
|
||||
|
||||
/* Single static config. */
|
||||
gw_info.hw_submodel = id;
|
||||
board_config = &_board_config;
|
||||
}
|
||||
|
||||
static void mcu_board_init(void)
|
||||
{
|
||||
gpio_pull_up_pins(gpioa, 0x0101); /* PA0,8 */
|
||||
@@ -44,9 +106,6 @@ static void mcu_board_init(void)
|
||||
|
||||
/* /RDY input line is externally pulled up. */
|
||||
gpio_configure_pin(gpiob, 15, GPI_floating);
|
||||
|
||||
/* Single static config. */
|
||||
board_config = &_board_config;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -24,6 +24,9 @@ static void clock_init(void)
|
||||
while (!(rcc->cr & RCC_CR_HSERDY))
|
||||
cpu_relax();
|
||||
|
||||
if (at32f4_series == AT32F403)
|
||||
delay_ms(2);
|
||||
|
||||
/* PLLs, scalers, muxes. */
|
||||
rcc->cfgr = (RCC_CFGR_PLLMUL(9) | /* PLL = 9*8MHz = 72MHz */
|
||||
RCC_CFGR_PLLSRC_PREDIV1 |
|
||||
@@ -35,11 +38,17 @@ static void clock_init(void)
|
||||
while (!(rcc->cr & RCC_CR_PLLRDY))
|
||||
cpu_relax();
|
||||
|
||||
if (at32f4_series == AT32F403)
|
||||
delay_us(200);
|
||||
|
||||
/* Switch to the externally-driven PLL for system clock. */
|
||||
rcc->cfgr |= RCC_CFGR_SW_PLL;
|
||||
while ((rcc->cfgr & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS_PLL)
|
||||
cpu_relax();
|
||||
|
||||
if (at32f4_series == AT32F403)
|
||||
delay_us(200);
|
||||
|
||||
/* Internal oscillator no longer needed. */
|
||||
rcc->cr &= ~RCC_CR_HSION;
|
||||
}
|
||||
@@ -67,13 +76,22 @@ static void identify_mcu(void)
|
||||
unsigned int flash_kb = *(uint16_t *)0x1ffff7e0;
|
||||
if (flash_kb <= 128)
|
||||
FLASH_PAGE_SIZE = 1024;
|
||||
|
||||
at32f4_series = *(uint8_t *)0x1ffff7f3; /* UID[95:88] */
|
||||
switch (at32f4_series) {
|
||||
case AT32F403:
|
||||
case AT32F415:
|
||||
break;
|
||||
default:
|
||||
early_fatal(4);
|
||||
}
|
||||
}
|
||||
|
||||
void stm32_init(void)
|
||||
{
|
||||
identify_mcu();
|
||||
cortex_init();
|
||||
identify_mcu();
|
||||
identify_board_config();
|
||||
clock_init();
|
||||
peripheral_init();
|
||||
cpu_sync();
|
||||
|
||||
Reference in New Issue
Block a user