This commit is contained in:
true 2023-11-01 21:06:48 -07:00
parent 15c0fe6b06
commit fc72a2a326
7 changed files with 412 additions and 412 deletions

View File

@ -1,24 +1,24 @@
/** /**
****************************************************************************** ******************************************************************************
* @file py32f0xx_it.h * @file py32f0xx_it.h
* @author MCU Application Team * @author MCU Application Team
* @brief This file contains the headers of the interrupt handlers. * @brief This file contains the headers of the interrupt handlers.
****************************************************************************** ******************************************************************************
* @attention * @attention
* *
* <h2><center>&copy; Copyright (c) Puya Semiconductor Co. * <h2><center>&copy; Copyright (c) Puya Semiconductor Co.
* All rights reserved.</center></h2> * All rights reserved.</center></h2>
* *
* <h2><center>&copy; Copyright (c) 2016 STMicroelectronics. * <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
* All rights reserved.</center></h2> * All rights reserved.</center></h2>
* *
* This software component is licensed by ST under BSD 3-Clause license, * This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the * the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at: * License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause * opensource.org/licenses/BSD-3-Clause
* *
****************************************************************************** ******************************************************************************
*/ */
/* Define to prevent recursive inclusion -------------------------------------*/ /* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __PY32F0XX_IT_H #ifndef __PY32F0XX_IT_H

View File

@ -56,12 +56,12 @@ static uint8_t calibrate = 0;
void adc_init() void adc_init()
{ {
// ensure ADC is DISABLED to write to registers // ensure ADC is DISABLED to write to registers
// this is opposite of what the RM says... the RM is wrong // this is opposite of what the RM says... the RM is wrong
ADC1->CR = 0; ADC1->CR = 0;
// enable VREFINT // enable VREFINT
ADC->CCR = ADC_CCR_VREFEN; // ADC_CCR_TSEN | ADC->CCR = ADC_CCR_VREFEN; // ADC_CCR_TSEN |
// enable end of conversion interrupt // enable end of conversion interrupt
ADC1->IER = ADC_IER_EOCIE; ADC1->IER = ADC_IER_EOCIE;
@ -73,18 +73,18 @@ void adc_init()
// default clock // default clock
ADC1->CFGR2 = 0; ADC1->CFGR2 = 0;
// configure scan channels, sampling time (11 = temp, 12 = vrefint) // configure scan channels, sampling time (11 = temp, 12 = vrefint)
ADC1->SMPR = SAMPLE_TIME; ADC1->SMPR = SAMPLE_TIME;
ADC1->CHSELR = CONF_SET1_AN | PROBE_AN | // note: SET1 and VREFEXT are ADC1->CHSELR = CONF_SET1_AN | PROBE_AN | // note: SET1 and VREFEXT are
CONF_MODE_AN | CONF_SET0_AN | // shared and reflect one chan CONF_MODE_AN | CONF_SET0_AN | // shared and reflect one chan
ADC_CHSELR_CHSEL12; ADC_CHSELR_CHSEL12;
// calibration configuration // calibration configuration
ADC1->CCSR = LL_ADC_CAL_SAMPLINGTIME_8CYCLES | ADC_CCSR_CALSEL; ADC1->CCSR = LL_ADC_CAL_SAMPLINGTIME_8CYCLES | ADC_CCSR_CALSEL;
// and enable the interrupt source in the NVIC // and enable the interrupt source in the NVIC
NVIC_EnableIRQ(ADC_COMP_IRQn); NVIC_EnableIRQ(ADC_COMP_IRQn);
NVIC_SetPriority(ADC_COMP_IRQn, 3); NVIC_SetPriority(ADC_COMP_IRQn, 3);
} }
/* /*
@ -110,7 +110,7 @@ void adc_go()
ADC1->CR = ADC_CR_ADEN; // enable ADC ADC1->CR = ADC_CR_ADEN; // enable ADC
adc_seq = 0; // reset channel read sequence adc_seq = 0; // reset channel read sequence
ADC1->ISR = 0x1e; // clear all interrupt flags (per DS; mistranslated) ADC1->ISR = 0x1e; // clear all interrupt flags (per DS; mistranslated)
ADC1->CR = ADC_CR_ADSTART | ADC_CR_ADEN; // begin conversion ADC1->CR = ADC_CR_ADSTART | ADC_CR_ADEN; // begin conversion
} }
/* /*
@ -149,12 +149,12 @@ uint8_t adc_next()
} }
// start ADC calibration // start ADC calibration
if (calibrate) { if (calibrate) {
adc_stop(); adc_stop();
// disable ADC and start calibration // disable ADC and start calibration
ADC1->CR &= ~(ADC_CR_ADEN); ADC1->CR &= ~(ADC_CR_ADEN);
ADC1->CR |= ADC_CR_ADCAL; ADC1->CR |= ADC_CR_ADCAL;
// clear cal flag; reset sequence to allow conversions to start // clear cal flag; reset sequence to allow conversions to start
calibrate = 0; calibrate = 0;
@ -170,7 +170,7 @@ uint8_t adc_next()
adc_go(); adc_go();
return ADC_SEQ_STARTUP; return ADC_SEQ_STARTUP;
} }
if (adc_seq == ADC_SEQ_RDY) { if (adc_seq == ADC_SEQ_RDY) {
// copy read data to history // copy read data to history

View File

@ -27,36 +27,36 @@ struct UConf conf = {0};
*/ */
void flash_set_timing(uint32_t *timing_table) void flash_set_timing(uint32_t *timing_table)
{ {
// load flash write timings from provided timing table // load flash write timings from provided timing table
// these are listed in the datasheet, but are also in ROM on the MCU // these are listed in the datasheet, but are also in ROM on the MCU
// note: if you decide to operate at a different frequency other than // note: if you decide to operate at a different frequency other than
// a supported frequency for which timing tables do not exist // a supported frequency for which timing tables do not exist
// in ROM, you'll have to figure out what these values actually mean, // in ROM, you'll have to figure out what these values actually mean,
// as the meaning of the values isn't documented in DS or RM // as the meaning of the values isn't documented in DS or RM
// note: the PRETPE and SMERTPE values seem to differ in MCU ROM from // note: the PRETPE and SMERTPE values seem to differ in MCU ROM from
// the values listed in the reference manual. this is true of // the values listed in the reference manual. this is true of
// all versions I have access to - English v1.0 and Chinese v1.2. // all versions I have access to - English v1.0 and Chinese v1.2.
// for example, @8MHz, RM says 0x5dc0 for PERTPE but ROM holds 0x6b60 // for example, @8MHz, RM says 0x5dc0 for PERTPE but ROM holds 0x6b60
// in testing, either ROM or RM value seems to work. // in testing, either ROM or RM value seems to work.
// note: the datasheet doesn't say it anywhere, but if flash is not unlocked, // note: the datasheet doesn't say it anywhere, but if flash is not unlocked,
// then flash timing values aren't writeable // then flash timing values aren't writeable
// apply flash table timing values // apply flash table timing values
FLASH->TS0 = (timing_table[0] >> 0) & 0xff; FLASH->TS0 = (timing_table[0] >> 0) & 0xff;
FLASH->TS3 = (timing_table[0] >> 8) & 0xff; FLASH->TS3 = (timing_table[0] >> 8) & 0xff;
FLASH->TS1 = (timing_table[0] >> 16) & 0x1ff; FLASH->TS1 = (timing_table[0] >> 16) & 0x1ff;
FLASH->TS2P = (timing_table[1] >> 0) & 0xff; FLASH->TS2P = (timing_table[1] >> 0) & 0xff;
FLASH->TPS3 = (timing_table[1] >> 16) & 0x7ff; FLASH->TPS3 = (timing_table[1] >> 16) & 0x7ff;
FLASH->PERTPE = timing_table[2]; // & 0x1ffff; FLASH->PERTPE = timing_table[2]; // & 0x1ffff;
FLASH->SMERTPE = timing_table[3]; // & 0x1ffff; FLASH->SMERTPE = timing_table[3]; // & 0x1ffff;
FLASH->PRGTPE = (timing_table[4] >> 0) & 0xffff; FLASH->PRGTPE = (timing_table[4] >> 0) & 0xffff;
FLASH->PRETPE = (timing_table[4] >> 16) & 0x7ff; FLASH->PRETPE = (timing_table[4] >> 16) & 0x7ff;
} }
/* /*
@ -66,48 +66,48 @@ void flash_set_timing(uint32_t *timing_table)
*/ */
__attribute__ ((long_call, section(".ramfunc"))) void flash_init() __attribute__ ((long_call, section(".ramfunc"))) void flash_init()
{ {
// unlock flash (necessary for writing timing registers // unlock flash (necessary for writing timing registers
FLASH->KEYR = FLASH_KEY1; FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2; FLASH->KEYR = FLASH_KEY2;
while (FLASH->CR & FLASH_CR_LOCK); // still locked? then stall forever while (FLASH->CR & FLASH_CR_LOCK); // still locked? then stall forever
// configure flash timings // configure flash timings
flash_set_timing(FLASH_HSI_8MHz); flash_set_timing(FLASH_HSI_8MHz);
// is the PF2/NRST pin configured as reset? // is the PF2/NRST pin configured as reset?
if ((FLASH->OPTR & FLASH_OPTR_NRST_MODE) == OB_RESET_MODE_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. // it is but shouldn't be, so let's configure it as GPIO.
// per datasheet, we must unlock FLASH->CR (already done above) // per datasheet, we must unlock FLASH->CR (already done above)
// and then unlock OPTLOCK // and then unlock OPTLOCK
FLASH->OPTKEYR = FLASH_OPTKEY1; FLASH->OPTKEYR = FLASH_OPTKEY1;
FLASH->OPTKEYR = FLASH_OPTKEY2; FLASH->OPTKEYR = FLASH_OPTKEY2;
while (FLASH->CR & FLASH_CR_OPTLOCK); // somehow, OB is still locked while (FLASH->CR & FLASH_CR_OPTLOCK); // somehow, OB is still locked
// write new OPTR values // 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; 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 // OB_BOR_ENABLE
// enable EOPIE (per DS, EOP isn't set unless EOPIE is set) // enable EOPIE (per DS, EOP isn't set unless EOPIE is set)
// and signal that we want to write option bits, // and signal that we want to write option bits,
FLASH->CR |= FLASH_CR_EOPIE | FLASH_CR_OPTSTRT; FLASH->CR |= FLASH_CR_EOPIE | FLASH_CR_OPTSTRT;
// then trigger the write by writing to a random address shown in the DS // then trigger the write by writing to a random address shown in the DS
*((__IO uint32_t *)(0x40022080)) = 0x55aa55aa; *((__IO uint32_t *)(0x40022080)) = 0x55aa55aa;
// wait for BSY to go low, then EOP to go high // wait for BSY to go low, then EOP to go high
while (FLASH->SR & FLASH_SR_BSY); while (FLASH->SR & FLASH_SR_BSY);
while (!(FLASH->SR & FLASH_SR_EOP)); while (!(FLASH->SR & FLASH_SR_EOP));
// do an OBL_LAUNCH reset to load the new option bits // do an OBL_LAUNCH reset to load the new option bits
// this must be done while OPTLOCK is cleared // this must be done while OPTLOCK is cleared
FLASH->CR |= FLASH_CR_OBL_LAUNCH; FLASH->CR |= FLASH_CR_OBL_LAUNCH;
// as the MCU should have reset, we should never get here. // as the MCU should have reset, we should never get here.
while(1); while(1);
} }
// re-lock flash when done // re-lock flash when done
FLASH->CR = FLASH_CR_LOCK; FLASH->CR = FLASH_CR_LOCK;
} }
/* /*
@ -115,46 +115,46 @@ __attribute__ ((long_call, section(".ramfunc"))) void flash_init()
*/ */
void flash_load_conf() void flash_load_conf()
{ {
int8_t i, j; int8_t i, j;
uint8_t loaded = 0; uint8_t loaded = 0;
struct UConf *fconf; struct UConf *fconf;
uint32_t *f32; uint32_t *f32;
uint32_t *u32; uint32_t *u32;
for (i = (UCONF_COUNT - 1); i >= 0; i--) { for (i = (UCONF_COUNT - 1); i >= 0; i--) {
fconf = (struct UConf *)(UCONF_FLASH_START + (UCONF_SIZE * i)); fconf = (struct UConf *)(UCONF_FLASH_START + (UCONF_SIZE * i));
f32 = (uint32_t *)fconf; f32 = (uint32_t *)fconf;
// empty flash = nothing here // empty flash = nothing here
if (fconf->crc32 == 0xffffffff) continue; if (fconf->crc32 == 0xffffffff) continue;
// invalid header = skip // invalid header = skip
if (fconf->conf_key != UCONF_KEY) continue; if (fconf->conf_key != UCONF_KEY) continue;
// calculate crc32 // calculate crc32
CRC->CR = CRC_CR_RESET; CRC->CR = CRC_CR_RESET;
while (CRC->CR & CRC_CR_RESET); while (CRC->CR & CRC_CR_RESET);
for (j = 0; j < ((UCONF_SIZE / 4) - 1); j++) { for (j = 0; j < ((UCONF_SIZE / 4) - 1); j++) {
CRC->DR = f32[j]; CRC->DR = f32[j];
} }
// check crc32 // check crc32
if (CRC->DR == f32[(UCONF_SIZE / 4) - 1]) { if (CRC->DR == f32[(UCONF_SIZE / 4) - 1]) {
// it passes. copy to RAM and break out // it passes. copy to RAM and break out
u32 = (uint32_t *)&conf; u32 = (uint32_t *)&conf;
for (j = 0; j < (UCONF_SIZE / 4); j++) { for (j = 0; j < (UCONF_SIZE / 4); j++) {
*u32++ = *f32++; *u32++ = *f32++;
} }
loaded = 1; loaded = 1;
break; break;
} }
} }
if (!loaded) { if (!loaded) {
// default config of zeroes works // default config of zeroes works
} }
} }
/* /*
@ -162,38 +162,38 @@ void flash_load_conf()
*/ */
__attribute__ ((long_call, section(".ramfunc"))) void flash_erase_page(uint32_t addr) __attribute__ ((long_call, section(".ramfunc"))) void flash_erase_page(uint32_t addr)
{ {
uint32_t primask; uint32_t primask;
// ensure flash is not busy // ensure flash is not busy
while (FLASH->SR & FLASH_SR_BSY); while (FLASH->SR & FLASH_SR_BSY);
// unlock flash // unlock flash
FLASH->KEYR = FLASH_KEY1; FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2; FLASH->KEYR = FLASH_KEY2;
while (FLASH->CR & FLASH_CR_LOCK); // still locked? then stall forever while (FLASH->CR & FLASH_CR_LOCK); // still locked? then stall forever
// enable EOPIE (per DS, EOP isn't set unless EOPIE is set) // enable EOPIE (per DS, EOP isn't set unless EOPIE is set)
// and signal that we want to erase a page // and signal that we want to erase a page
FLASH->SR = FLASH_SR_EOP; FLASH->SR = FLASH_SR_EOP;
FLASH->CR |= FLASH_CR_EOPIE | FLASH_CR_PER; FLASH->CR |= FLASH_CR_EOPIE | FLASH_CR_PER;
// disable interrupts // disable interrupts
primask = __get_PRIMASK(); primask = __get_PRIMASK();
__disable_irq(); __disable_irq();
// trigger the erase by writing to a random address shown in the DS // trigger the erase by writing to a random address shown in the DS
*((__IO uint32_t *)(addr)) = 0x55aa55aa; *((__IO uint32_t *)(addr)) = 0x55aa55aa;
// ensure flash is not busy, then wait for end of programming // ensure flash is not busy, then wait for end of programming
while (FLASH->SR & FLASH_SR_BSY); while (FLASH->SR & FLASH_SR_BSY);
while (!(FLASH->SR & FLASH_SR_EOP)); while (!(FLASH->SR & FLASH_SR_EOP));
FLASH->SR |= FLASH_SR_EOP; FLASH->SR |= FLASH_SR_EOP;
// re-lock flash // re-lock flash
FLASH->CR = FLASH_CR_LOCK; FLASH->CR = FLASH_CR_LOCK;
// re-enable interrupts // re-enable interrupts
__set_PRIMASK(primask); __set_PRIMASK(primask);
} }
/* /*
@ -203,51 +203,51 @@ __attribute__ ((long_call, section(".ramfunc"))) void flash_erase_page(uint32_t
*/ */
__attribute__ ((long_call, section(".ramfunc"))) void flash_write_page(uint32_t addr, uint32_t *data) __attribute__ ((long_call, section(".ramfunc"))) void flash_write_page(uint32_t addr, uint32_t *data)
{ {
uint32_t primask; uint32_t primask;
uint8_t i; uint8_t i;
uint32_t *src; uint32_t *src;
uint32_t *dst; uint32_t *dst;
// ensure flash is not busy // ensure flash is not busy
while (FLASH->SR & FLASH_SR_BSY); while (FLASH->SR & FLASH_SR_BSY);
// unlock flash // unlock flash
FLASH->KEYR = FLASH_KEY1; FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2; FLASH->KEYR = FLASH_KEY2;
while (FLASH->CR & FLASH_CR_LOCK); // still locked? then stall forever while (FLASH->CR & FLASH_CR_LOCK); // still locked? then stall forever
// enable EOPIE (per DS, EOP isn't set unless EOPIE is set) // enable EOPIE (per DS, EOP isn't set unless EOPIE is set)
// and signal that we want to write a page // and signal that we want to write a page
FLASH->SR = FLASH_SR_EOP; FLASH->SR = FLASH_SR_EOP;
FLASH->CR |= FLASH_CR_EOPIE | FLASH_CR_PG; FLASH->CR |= FLASH_CR_EOPIE | FLASH_CR_PG;
// disable interrupts // disable interrupts
primask = __get_PRIMASK(); primask = __get_PRIMASK();
__disable_irq(); __disable_irq();
// write data to flash // write data to flash
src = data; src = data;
dst = (uint32_t *)addr; dst = (uint32_t *)addr;
for (i = 0; i < (FLASH_PAGE_SIZE / 4) - 1; i++) { for (i = 0; i < (FLASH_PAGE_SIZE / 4) - 1; i++) {
*dst++ = *src++; *dst++ = *src++;
} }
// for the last word, enable the PGSTRT bit then write the word to commit to flash // for the last word, enable the PGSTRT bit then write the word to commit to flash
FLASH->CR |= FLASH_CR_PGSTRT; FLASH->CR |= FLASH_CR_PGSTRT;
*dst = *src; *dst = *src;
// ensure flash is not busy, then wait for end of programming // ensure flash is not busy, then wait for end of programming
while (FLASH->SR & FLASH_SR_BSY); while (FLASH->SR & FLASH_SR_BSY);
while (!(FLASH->SR & FLASH_SR_EOP)); while (!(FLASH->SR & FLASH_SR_EOP));
FLASH->SR |= FLASH_SR_EOP; FLASH->SR |= FLASH_SR_EOP;
// re-lock flash // re-lock flash
FLASH->CR = FLASH_CR_LOCK; FLASH->CR = FLASH_CR_LOCK;
// re-enable interrupts // re-enable interrupts
__set_PRIMASK(primask); __set_PRIMASK(primask);
} }
/* /*
@ -256,95 +256,95 @@ __attribute__ ((long_call, section(".ramfunc"))) void flash_write_page(uint32_t
*/ */
void flash_commit_conf() void flash_commit_conf()
{ {
uint32_t i; uint32_t i;
uint8_t flash_idx = 0; uint8_t flash_idx = 0;
uint8_t flash_full = 0; uint8_t flash_full = 0;
struct UConf *fconf; struct UConf *fconf;
uint32_t *f32, *u32; uint32_t *f32, *u32;
uint32_t write[(FLASH_PAGE_SIZE / 4)]; uint32_t write[(FLASH_PAGE_SIZE / 4)];
// find first free page index // find first free page index
for (i = 0; i < UCONF_COUNT; i++) { for (i = 0; i < UCONF_COUNT; i++) {
fconf = (struct UConf *)(UCONF_FLASH_START + (UCONF_SIZE * i)); fconf = (struct UConf *)(UCONF_FLASH_START + (UCONF_SIZE * i));
if ((fconf->crc32 == 0xffffffff) || (fconf->conf_key != UCONF_KEY)) { if ((fconf->crc32 == 0xffffffff) || (fconf->conf_key != UCONF_KEY)) {
flash_idx = i; flash_idx = i;
break; break;
} }
} }
// if all pages are occupied, we'll erase all the pages // if all pages are occupied, we'll erase all the pages
if (i == UCONF_COUNT) { if (i == UCONF_COUNT) {
flash_full = 1; flash_full = 1;
} }
// ensure live config header is correct, and calculate CRC // ensure live config header is correct, and calculate CRC
conf.conf_key = UCONF_KEY; conf.conf_key = UCONF_KEY;
conf.update_cntr++; conf.update_cntr++;
u32 = (uint32_t *)&conf; u32 = (uint32_t *)&conf;
CRC->CR = CRC_CR_RESET; CRC->CR = CRC_CR_RESET;
while (CRC->CR & CRC_CR_RESET); while (CRC->CR & CRC_CR_RESET);
for (i = 0; i < (UCONF_SIZE / 4) - 1; i++) { for (i = 0; i < (UCONF_SIZE / 4) - 1; i++) {
CRC->DR = u32[i]; CRC->DR = u32[i];
} }
u32[(UCONF_SIZE / 4) - 1] = CRC->DR; u32[(UCONF_SIZE / 4) - 1] = CRC->DR;
// do we need to actually update data? // do we need to actually update data?
// check checksum of our data against checksum of prior entry // check checksum of our data against checksum of prior entry
if (flash_idx) { if (flash_idx) {
fconf = (struct UConf *)(UCONF_FLASH_START + (UCONF_SIZE * (flash_idx - 1))); fconf = (struct UConf *)(UCONF_FLASH_START + (UCONF_SIZE * (flash_idx - 1)));
if (fconf->crc32 == conf.crc32) { if (fconf->crc32 == conf.crc32) {
// nothing to update; we can break out // nothing to update; we can break out
return; return;
} }
} }
// set empty write buffer to 0xff // set empty write buffer to 0xff
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
write[i] = 0xffffffff; write[i] = 0xffffffff;
} }
// set write buffer // set write buffer
u32 = (uint32_t *)write; u32 = (uint32_t *)write;
// if this is the second entry in a flash page, // if this is the second entry in a flash page,
// copy first half of flash page from ROM to the write buffer, // copy first half of flash page from ROM to the write buffer,
// as our config size (64 bytes) is smaller than the page write size (128 bytes) // as our config size (64 bytes) is smaller than the page write size (128 bytes)
if (flash_idx & 1) { if (flash_idx & 1) {
f32 = (uint32_t *)fconf; f32 = (uint32_t *)fconf;
for (i = 0; i < (UCONF_SIZE / 4); i++) { for (i = 0; i < (UCONF_SIZE / 4); i++) {
*u32++ = *f32++; *u32++ = *f32++;
} }
} }
// correct flash_idx if it is out of bounds // correct flash_idx if it is out of bounds
// (we will usually have 1-8, only getting 0 on the very first write) // (we will usually have 1-8, only getting 0 on the very first write)
if (flash_idx == UCONF_COUNT) { if (flash_idx == UCONF_COUNT) {
flash_idx = 0; flash_idx = 0;
} }
// copy user config from RAM to write buffer at the appropriate offset // copy user config from RAM to write buffer at the appropriate offset
f32 = (uint32_t *)&conf; f32 = (uint32_t *)&conf;
for (i = 0; i < (UCONF_SIZE / 4); i++) { for (i = 0; i < (UCONF_SIZE / 4); i++) {
*u32++ = *f32++; *u32++ = *f32++;
} }
// we now need the flash page boundary, so remove lowest bit from flash_idx // we now need the flash page boundary, so remove lowest bit from flash_idx
flash_idx &= ~1; flash_idx &= ~1;
// erase this page // erase this page
flash_erase_page(UCONF_FLASH_START + (UCONF_SIZE * flash_idx)); flash_erase_page(UCONF_FLASH_START + (UCONF_SIZE * flash_idx));
// commit to flash // commit to flash
flash_write_page(UCONF_FLASH_START + (UCONF_SIZE * flash_idx), write); flash_write_page(UCONF_FLASH_START + (UCONF_SIZE * flash_idx), write);
// if flash was full, erase other pages // if flash was full, erase other pages
if (flash_full) { if (flash_full) {
for (i = (UCONF_FLASH_START + FLASH_PAGE_SIZE); i < FLASH_END; i += FLASH_PAGE_SIZE) { for (i = (UCONF_FLASH_START + FLASH_PAGE_SIZE); i < FLASH_END; i += FLASH_PAGE_SIZE) {
flash_erase_page(i); flash_erase_page(i);
} }
} }
} }

View File

@ -129,31 +129,31 @@ void led_buzz(uint8_t buzz)
*/ */
void led_init() void led_init()
{ {
LL_TIM_InitTypeDef tim = {0}; LL_TIM_InitTypeDef tim = {0};
LL_TIM_OC_InitTypeDef pwm = {0}; LL_TIM_OC_InitTypeDef pwm = {0};
// configure timer // configure timer
tim.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; tim.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
tim.CounterMode = LL_TIM_COUNTERMODE_UP; tim.CounterMode = LL_TIM_COUNTERMODE_UP;
tim.Prescaler = 0; tim.Prescaler = 0;
/* PWM period = 1000 */ /* PWM period = 1000 */
tim.Autoreload = 1000 - 1; // ~8KHz operation, roughly 10-bit tim.Autoreload = 1000 - 1; // ~8KHz operation, roughly 10-bit
tim.RepetitionCounter = 0; tim.RepetitionCounter = 0;
LL_TIM_Init(TIM_RGB, &tim); LL_TIM_Init(TIM_RGB, &tim);
// configure timer outputs // configure timer outputs
pwm.OCMode = LL_TIM_OCMODE_PWM2; pwm.OCMode = LL_TIM_OCMODE_PWM2;
pwm.OCState = LL_TIM_OCSTATE_ENABLE; pwm.OCState = LL_TIM_OCSTATE_ENABLE;
pwm.OCPolarity = LL_TIM_OCPOLARITY_HIGH; pwm.OCPolarity = LL_TIM_OCPOLARITY_HIGH;
pwm.OCIdleState = LL_TIM_OCIDLESTATE_LOW; pwm.OCIdleState = LL_TIM_OCIDLESTATE_LOW;
pwm.CompareValue = 0; pwm.CompareValue = 0;
LL_TIM_OC_Init(TIM_RGB, TIM_RGB_R_CH, &pwm); LL_TIM_OC_Init(TIM_RGB, TIM_RGB_R_CH, &pwm);
LL_TIM_OC_Init(TIM_RGB, TIM_RGB_G_CH, &pwm); LL_TIM_OC_Init(TIM_RGB, TIM_RGB_G_CH, &pwm);
LL_TIM_OC_Init(TIM_RGB, TIM_RGB_B_CH, &pwm); LL_TIM_OC_Init(TIM_RGB, TIM_RGB_B_CH, &pwm);
// clear all outputs // clear all outputs
@ -163,7 +163,7 @@ void led_init()
// enable timer // enable timer
LL_TIM_EnableAllOutputs(TIM_RGB); LL_TIM_EnableAllOutputs(TIM_RGB);
LL_TIM_EnableCounter(TIM_RGB); LL_TIM_EnableCounter(TIM_RGB);
// other setup // other setup
led_mode = MODE_RGB; led_mode = MODE_RGB;

View File

@ -31,68 +31,68 @@ uint32_t uptime;
static inline void gpio_init() static inline void gpio_init()
{ {
// set registers manually instead of with // set registers manually instead of with
// LL functions to save space. // LL functions to save space.
// though we probably don't _need_ this space... // though we probably don't _need_ this space...
// PF2=OUT(high), low speed // PF2=OUT(high), low speed
// unused pins are analog // unused pins are analog
GPIOF->ODR = (1 << 2); GPIOF->ODR = (1 << 2);
GPIOF->MODER = 0xFFFFFCDF; GPIOF->MODER = 0xFFFFFCDF;
// set I2C outputs as open drain // set I2C outputs as open drain
GPIOA->OTYPER = 0x000c; GPIOA->OTYPER = 0x000c;
// enable pullups on I2C outputs // enable pullups on I2C outputs
GPIOA->PUPDR = 0x24000050; GPIOA->PUPDR = 0x24000050;
// datasheet doesn't say what the speeds are for GPIO... // datasheet doesn't say what the speeds are for GPIO...
// so set SWDIO to very high speed, PA12 low speed, all other outputs as high speed // so set SWDIO to very high speed, PA12 low speed, all other outputs as high speed
GPIOA->OSPEEDR = 0x2C002AA0; GPIOA->OSPEEDR = 0x2C002AA0;
// alternate function select // alternate function select
// PA6=T3C1, PA5=T3C2, PA4=T3C3, PA3=I2C_SCL, PA2=I2C_SDA // PA6=T3C1, PA5=T3C2, PA4=T3C3, PA3=I2C_SCL, PA2=I2C_SDA
GPIOA->AFR[0] = 0x01DDCC00; GPIOA->AFR[0] = 0x01DDCC00;
// PA12=OUT(high) // PA12=OUT(high)
GPIOA->ODR = (1 << 12); GPIOA->ODR = (1 << 12);
// PA14=ALT, PA13=ALT, PA12=OUT, PA11=OUT // PA14=ALT, PA13=ALT, PA12=OUT, PA11=OUT
// PA7=AN, PA6=AF, PA5=AF, PA4=AF // PA7=AN, PA6=AF, PA5=AF, PA4=AF
// PA3=AF, PA2=AF, PA1=AN, PA0=AN // PA3=AF, PA2=AF, PA1=AN, PA0=AN
// unused pins are digital inputs // unused pins are digital inputs
GPIOA->MODER = 0x2900EAAF; GPIOA->MODER = 0x2900EAAF;
// PB1=OUT(HIGH), PB0=AN // PB1=OUT(HIGH), PB0=AN
// unused pins are analog, all outputs are low speed // unused pins are analog, all outputs are low speed
GPIOB->OSPEEDR = 0x00000000; GPIOB->OSPEEDR = 0x00000000;
GPIOB->ODR = (1 << 1); GPIOB->ODR = (1 << 1);
GPIOB->MODER = 0xfffffff7; GPIOB->MODER = 0xfffffff7;
} }
static inline void clk_init() static inline void clk_init()
{ {
// run all buses at core clock speed // run all buses at core clock speed
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
// enable GPIO and peripheral clocks // enable GPIO and peripheral clocks
RCC->IOPENR = LL_IOP_GRP1_PERIPH_GPIOA | RCC->IOPENR = LL_IOP_GRP1_PERIPH_GPIOA |
LL_IOP_GRP1_PERIPH_GPIOB | LL_IOP_GRP1_PERIPH_GPIOB |
LL_IOP_GRP1_PERIPH_GPIOF; LL_IOP_GRP1_PERIPH_GPIOF;
RCC->AHBENR |= LL_AHB1_GRP1_PERIPH_CRC; RCC->AHBENR |= LL_AHB1_GRP1_PERIPH_CRC;
RCC->APBENR1 = LL_APB1_GRP1_PERIPH_TIM3; RCC->APBENR1 = LL_APB1_GRP1_PERIPH_TIM3;
RCC->APBENR2 = LL_APB1_GRP2_PERIPH_ADC1; RCC->APBENR2 = LL_APB1_GRP2_PERIPH_ADC1;
} }
static inline void systick_init() static inline void systick_init()
{ {
// configure nvic // configure nvic
NVIC_EnableIRQ(SysTick_IRQn); NVIC_EnableIRQ(SysTick_IRQn);
NVIC_SetPriority(SysTick_IRQn, 0); NVIC_SetPriority(SysTick_IRQn, 0);
// configure timebase with interrupt at 4096Hz // configure timebase with interrupt at 4096Hz
// this assumes we'll always be running at 8MHz // this assumes we'll always be running at 8MHz
SysTick_Config((8000000 / 4096) - 1); SysTick_Config((8000000 / 4096) - 1);
} }
/* /*
@ -101,35 +101,35 @@ static inline void systick_init()
*/ */
int main() int main()
{ {
// base hardware initialization // base hardware initialization
clk_init(); clk_init();
flash_init(); // also configures option bytes to enable PF2, if necessary flash_init(); // also configures option bytes to enable PF2, if necessary
gpio_init(); gpio_init();
// load configuration from flash // load configuration from flash
flash_load_conf(); flash_load_conf();
// peripheral initialization // peripheral initialization
led_init(); led_init();
adc_init(); adc_init();
// mainline loop interrupt // mainline loop interrupt
systick_init(); systick_init();
// let's go // let's go
__enable_irq(); __enable_irq();
while (1) { while (1) {
// run LED programs out of interrupt context at 256Hz // run LED programs out of interrupt context at 256Hz
if (!(ctr & 0xf)) { if (!(ctr & 0xf)) {
if (userio_get_mode() == MODE_FUN) { if (userio_get_mode() == MODE_FUN) {
rgbprog_run(); rgbprog_run();
} }
} }
// nap time // nap time
__WFI(); __WFI();
} }
} }
/* /*
@ -140,43 +140,43 @@ volatile uint16_t adc_sec; // ADC cycles per second (used w/debugger)
void SysTick_Handler(void) void SysTick_Handler(void)
{ {
uint16_t cs; uint16_t cs;
ctr++; ctr++;
// run LED programs quickly // run LED programs quickly
led_next(); led_next();
// limit counter to 4096 counts // limit counter to 4096 counts
ctr &= 0xfff; ctr &= 0xfff;
if (!ctr) { if (!ctr) {
uptime++; uptime++;
adc_sec = adc_ctr; adc_sec = adc_ctr;
adc_ctr = 0; adc_ctr = 0;
} }
// run main logic at 2048Hz // run main logic at 2048Hz
if (!(ctr & 0x1)) { if (!(ctr & 0x1)) {
// shifted counter for use in the program // shifted counter for use in the program
cs = ctr >> 1; cs = ctr >> 1;
// adc tested to result in about 61 reads/second // adc tested to result in about 61 reads/second
if (!adc_next()) { if (!adc_next()) {
// adc has new computed results // adc has new computed results
adc_ctr++; adc_ctr++;
// start using ADC results only after the first cycle // start using ADC results only after the first cycle
if (uptime || cs) { if (uptime || cs) {
// figure out knobs, buttons, switches // figure out knobs, buttons, switches
userio_parse(); userio_parse();
// initialize randomness // initialize randomness
rand_init((knob[0] << 8) | knob[1]); rand_init((knob[0] << 8) | knob[1]);
// show probe measurement results, or if not in a measurement mode, // show probe measurement results, or if not in a measurement mode,
// run RGBLED program // run RGBLED program
probe_measure(); probe_measure();
} }
} }
} }
} }

View File

@ -1,24 +1,24 @@
/** /**
****************************************************************************** ******************************************************************************
* @file py32f0xx_it.c * @file py32f0xx_it.c
* @author MCU Application Team * @author MCU Application Team
* @brief Interrupt Service Routines. * @brief Interrupt Service Routines.
****************************************************************************** ******************************************************************************
* @attention * @attention
* *
* <h2><center>&copy; Copyright (c) Puya Semiconductor Co. * <h2><center>&copy; Copyright (c) Puya Semiconductor Co.
* All rights reserved.</center></h2> * All rights reserved.</center></h2>
* *
* <h2><center>&copy; Copyright (c) 2016 STMicroelectronics. * <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
* All rights reserved.</center></h2> * All rights reserved.</center></h2>
* *
* This software component is licensed by ST under BSD 3-Clause license, * This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the * the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at: * License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause * opensource.org/licenses/BSD-3-Clause
* *
****************************************************************************** ******************************************************************************
*/ */
/* Includes ------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
#include "py32f0xx_it.h" #include "py32f0xx_it.h"
@ -36,15 +36,15 @@
/* Cortex-M0+ Processor Interruption and Exception Handlers */ /* Cortex-M0+ Processor Interruption and Exception Handlers */
/******************************************************************************/ /******************************************************************************/
/** /**
* @brief This function handles Non maskable interrupt. * @brief This function handles Non maskable interrupt.
*/ */
void NMI_Handler(void) void NMI_Handler(void)
{ {
} }
/** /**
* @brief This function handles Hard fault interrupt. * @brief This function handles Hard fault interrupt.
*/ */
void HardFault_Handler(void) void HardFault_Handler(void)
{ {
while (1) while (1)
@ -53,22 +53,22 @@ void HardFault_Handler(void)
} }
/** /**
* @brief This function handles System service call via SWI instruction. * @brief This function handles System service call via SWI instruction.
*/ */
void SVC_Handler(void) void SVC_Handler(void)
{ {
} }
/** /**
* @brief This function handles Pendable request for system service. * @brief This function handles Pendable request for system service.
*/ */
void PendSV_Handler(void) void PendSV_Handler(void)
{ {
} }
/** /**
* @brief This function handles System tick timer. * @brief This function handles System tick timer.
*/ */
/* /*
void SysTick_Handler(void) void SysTick_Handler(void)
{ {

View File

@ -58,7 +58,7 @@ static uint8_t mode = 0xff;
static uint8_t mode_next; static uint8_t mode_next;
static uint8_t mode_count; static uint8_t mode_count;
static const int16_t mode_targets[] = { static const int16_t mode_targets[] = {
MODE_CONT_TARGET, MODE_FUN_TARGET, MODE_DIODE_TARGET MODE_CONT_TARGET, MODE_FUN_TARGET, MODE_DIODE_TARGET
}; };
uint8_t knob[2]; uint8_t knob[2];
@ -70,11 +70,11 @@ static uint16_t btn_held = 0;
void userio_parse() void userio_parse()
{ {
uint8_t i; uint8_t i;
int16_t m, w; int16_t m, w;
uint32_t x; uint32_t x;
// button // button
{ {
// debounce is handled by the fact that we've had to have averaged // debounce is handled by the fact that we've had to have averaged
// about 16ms of measured hold time below the zero threshold. // about 16ms of measured hold time below the zero threshold.
@ -92,7 +92,7 @@ void userio_parse()
} }
} }
// mode // mode
if (!btn) { if (!btn) {
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
// clear mode_count if we aren't actively changing modes // clear mode_count if we aren't actively changing modes