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
* @author MCU Application Team
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) Puya Semiconductor Co.
* All rights reserved.</center></h2>
*
* <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
* All rights reserved.</center></h2>
*
* 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
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
******************************************************************************
* @file py32f0xx_it.h
* @author MCU Application Team
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) Puya Semiconductor Co.
* All rights reserved.</center></h2>
*
* <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
* All rights reserved.</center></h2>
*
* 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
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __PY32F0XX_IT_H

View File

@ -56,12 +56,12 @@ static uint8_t calibrate = 0;
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
ADC1->CR = 0;
ADC1->CR = 0;
// enable VREFINT
ADC->CCR = ADC_CCR_VREFEN; // ADC_CCR_TSEN |
// enable VREFINT
ADC->CCR = ADC_CCR_VREFEN; // ADC_CCR_TSEN |
// enable end of conversion interrupt
ADC1->IER = ADC_IER_EOCIE;
@ -73,18 +73,18 @@ void adc_init()
// default clock
ADC1->CFGR2 = 0;
// configure scan channels, sampling time (11 = temp, 12 = vrefint)
ADC1->SMPR = SAMPLE_TIME;
// configure scan channels, sampling time (11 = temp, 12 = vrefint)
ADC1->SMPR = SAMPLE_TIME;
ADC1->CHSELR = CONF_SET1_AN | PROBE_AN | // note: SET1 and VREFEXT are
CONF_MODE_AN | CONF_SET0_AN | // shared and reflect one chan
ADC_CHSELR_CHSEL12;
CONF_MODE_AN | CONF_SET0_AN | // shared and reflect one chan
ADC_CHSELR_CHSEL12;
// 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
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
adc_seq = 0; // reset channel read sequence
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
if (calibrate) {
if (calibrate) {
adc_stop();
// disable ADC and start calibration
ADC1->CR &= ~(ADC_CR_ADEN);
ADC1->CR |= ADC_CR_ADCAL;
ADC1->CR &= ~(ADC_CR_ADEN);
ADC1->CR |= ADC_CR_ADCAL;
// clear cal flag; reset sequence to allow conversions to start
calibrate = 0;
@ -170,7 +170,7 @@ uint8_t adc_next()
adc_go();
return ADC_SEQ_STARTUP;
}
}
if (adc_seq == ADC_SEQ_RDY) {
// copy read data to history

View File

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

View File

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

View File

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

View File

@ -1,24 +1,24 @@
/**
******************************************************************************
* @file py32f0xx_it.c
* @author MCU Application Team
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) Puya Semiconductor Co.
* All rights reserved.</center></h2>
*
* <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
* All rights reserved.</center></h2>
*
* 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
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
******************************************************************************
* @file py32f0xx_it.c
* @author MCU Application Team
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) Puya Semiconductor Co.
* All rights reserved.</center></h2>
*
* <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
* All rights reserved.</center></h2>
*
* 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
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "py32f0xx_it.h"
@ -36,15 +36,15 @@
/* 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)
{
}
/**
* @brief This function handles Hard fault interrupt.
*/
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
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)
{
}
/**
* @brief This function handles Pendable request for system service.
*/
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
}
/**
* @brief This function handles System tick timer.
*/
* @brief This function handles System tick timer.
*/
/*
void SysTick_Handler(void)
{

View File

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