diff --git a/include/testo.h b/include/testo.h index 08ec726..1646590 100644 --- a/include/testo.h +++ b/include/testo.h @@ -48,7 +48,7 @@ #define CONF_MODE_AN ADC_CHSELR_CHSEL7 #define RGBSEL0_PORT GPIOA -#define RGBSEL0_PIN 12 // output, default low +#define RGBSEL0_PIN 12 // output, default high #define UART_PORT GPIOA #define UART_DEV USART1 @@ -64,7 +64,7 @@ #define CONF_SET0_AN ADC_CHSELR_CHSEL8 #define RGBSEL1_PORT GPIOB -#define RGBSEL1_PIN 1 // output, default low +#define RGBSEL1_PIN 1 // output, default high #define PROBESEL_PORT GPIOF diff --git a/lib/py32f0xx-ll/src/py32f0xx_ll_flash.c b/lib/py32f0xx-ll/src/py32f0xx_ll_flash.c index 4eaa3d0..c3df089 100644 --- a/lib/py32f0xx-ll/src/py32f0xx_ll_flash.c +++ b/lib/py32f0xx-ll/src/py32f0xx_ll_flash.c @@ -871,7 +871,7 @@ ErrorStatus LL_FLASH_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit) FLASH->CR|=FLASH_CR_OPTSTRT; /* set bit EOPIE */ - // FLASH->CR|=FLASH_CR_EOPIE; + FLASH->CR|=FLASH_CR_EOPIE; /* trigger program */ *((__IO uint32_t *)(0x40022080))=0xff; diff --git a/py32f030x6.ld b/py32f030x6.ld index 08f87cc..4664fb4 100644 --- a/py32f030x6.ld +++ b/py32f030x6.ld @@ -110,7 +110,8 @@ SECTIONS _sdata = .; /* create a global symbol at data start */ *(.data) /* .data sections */ *(.data*) /* .data* sections */ - + *(.ramfunc*) + . = ALIGN(4); _edata = .; /* define a global symbol at data end */ } >RAM AT> FLASH diff --git a/py32f030x6_bl.ld b/py32f030x6_bl.ld index 50dc8c3..e2d6259 100644 --- a/py32f030x6_bl.ld +++ b/py32f030x6_bl.ld @@ -108,6 +108,7 @@ SECTIONS _sdata = .; /* create a global symbol at data start */ *(.data) /* .data sections */ *(.data*) /* .data* sections */ + *(.ramfunc*) . = ALIGN(4); _edata = .; /* define a global symbol at data end */ diff --git a/src/flash.c b/src/flash.c index 67ac6e4..b1f0a2d 100644 --- a/src/flash.c +++ b/src/flash.c @@ -47,20 +47,12 @@ void flash_optr_checkfix() } } -/* - * manually load values into flash option byte, to configure - * the BOR and configure the reset pin to be PF2. - */ -void flash_optr_set() -{ - FLASH->OPTR &= (FLASH_OPTR_BOR_EN_Msk | FLASH_OPTR_BOR_LEV_Msk | FLASH_OPTR_NRST_MODE_Msk); - FLASH->OPTR |= OB_BOR_ENABLE | OB_BOR_LEVEL_2p3_2p4 | OB_RESET_MODE_GPIO; -} - -void flash_init() +void flash_write_timings_8MHz() { // load flash write timings for 8MHz operation // (these are listed in the datasheet) + // note: if you decide to operate at a different frequency, then either + // update these values, or reduce speed to 8MHz when writing to flash FLASH->TS0 = 0x3c; FLASH->TS2P = 0x3c; FLASH->TS3 = 0x3c; @@ -72,4 +64,45 @@ void flash_init() FLASH->SMERTPE = 0x5dc0; FLASH->PRGTPE = 0x1f40; FLASH->PRETPE = 0x640; +} + +__attribute__ ((long_call, section(".ramfunc"))) void flash_init() +{ + // configure flash timings + flash_write_timings_8MHz(); + + // is the PF2/NRST pin configured as reset? + if ((FLASH->OPTR & FLASH_OPTR_NRST_MODE) == OB_RESET_MODE_RESET) { + // it is but shouldn't be, so let's configure it as GPIO. + + // per datasheet, we must unlock FLASH->CR and then unlock OPTLOCK + FLASH->KEYR = FLASH_KEY1; + FLASH->KEYR = FLASH_KEY2; + if (FLASH->CR & FLASH_CR_LOCK) return; // somehow, flash is still locked + + FLASH->OPTKEYR = FLASH_OPTKEY1; + FLASH->OPTKEYR = FLASH_OPTKEY2; + if (FLASH->CR & FLASH_CR_OPTLOCK) return; // somehow, OB is still locked + + // write new OPTR values + FLASH->OPTR = OB_RESET_MODE_GPIO | OB_WWDG_SW | OB_IWDG_SW | OB_BOR_LEVEL_2p3_2p4 | FLASH_OPTR_RDP_LEVEL_0; + // OB_BOR_ENABLE + + // enable EOPIE (per DS, EOP isn't set unless EOPIE is set) + // and signal that we want to write option bits, + // then trigger the write by writing to a random address shown in the DS + FLASH->CR |= FLASH_CR_EOPIE | FLASH_CR_OPTSTRT; + *((__IO uint32_t *)(0x40022080)) = 0x55aa55aa; + + // wait for BSY to go low, then EOP to go high + while (FLASH->SR & FLASH_SR_BSY); + while (!(FLASH->SR & FLASH_SR_EOP)); + + // do an OBL_LAUNCH reset to load the new option bits + // this must be done while OPTLOCK is cleared + FLASH->CR |= FLASH_CR_OBL_LAUNCH; + + // as the MCU should have reset, we should never get here. + while(1); + } } \ No newline at end of file diff --git a/src/main.c b/src/main.c index 193d17b..d4b3d31 100644 --- a/src/main.c +++ b/src/main.c @@ -27,7 +27,12 @@ static inline void gpio_init() // LL functions to save space. // though we probably don't _need_ this space... - // set I2C outputs as open drain + // PF2=OUT(high), low speed + // unused pins are analog + GPIOF->ODR = (1 << 2); + GPIOF->MODER = 0xFFFFFCDF; + + // set I2C outputs as open drain GPIOA->OTYPER = 0x000c; // enable pullups on I2C outputs GPIOA->PUPDR = 0x24000050; @@ -37,6 +42,8 @@ static inline void gpio_init() // alternate function select // PA6=T3C1, PA5=T3C2, PA4=T3C3, PA3=I2C_SCL, PA2=I2C_SDA GPIOA->AFR[0] = 0x01DDCC00; + // PA12=OUT(high) + GPIOA->ODR = (1 << 12); // PA14=ALT, PA13=ALT, PA12=OUT, PA11=OUT // PA7=AN, PA6=AF, PA5=AF, PA4=AF @@ -45,15 +52,11 @@ static inline void gpio_init() GPIOA->MODER = 0x2900EAAF; - // PB1=OUT, PB0=AN + // PB1=OUT(HIGH), PB0=AN // unused pins are analog, all outputs are low speed GPIOB->OSPEEDR = 0x00000000; + GPIOB->ODR = (1 << 1); GPIOB->MODER = 0xfffffff7; - - // PF2=OUT(low), low speed - // unused pins are analog - GPIOF->ODR = (1 << 2); - GPIOF->MODER = 0xFFFFFCDF; } static inline void clk_init() @@ -91,7 +94,7 @@ int main() { // base hardware initialization clk_init(); - flash_init(); // also configures option bytes, if necessary + flash_init(); // also configures option bytes to enable PF2, if necessary gpio_init(); // peripheral initialization @@ -119,7 +122,7 @@ int main() * main application interrupt */ -void SysTick_Handler(void) +__attribute__ ((long_call, section(".ramfunc"))) void SysTick_Handler(void) { uint16_t cs;