tabs lol
This commit is contained in:
parent
15c0fe6b06
commit
fc72a2a326
|
@ -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>© Copyright (c) Puya Semiconductor Co.
|
* <h2><center>© Copyright (c) Puya Semiconductor Co.
|
||||||
* All rights reserved.</center></h2>
|
* All rights reserved.</center></h2>
|
||||||
*
|
*
|
||||||
* <h2><center>© Copyright (c) 2016 STMicroelectronics.
|
* <h2><center>© 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
|
||||||
|
|
32
src/adc.c
32
src/adc.c
|
@ -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
|
||||||
|
|
466
src/flash.c
466
src/flash.c
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
34
src/led.c
34
src/led.c
|
@ -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;
|
||||||
|
|
180
src/main.c
180
src/main.c
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>© Copyright (c) Puya Semiconductor Co.
|
* <h2><center>© Copyright (c) Puya Semiconductor Co.
|
||||||
* All rights reserved.</center></h2>
|
* All rights reserved.</center></h2>
|
||||||
*
|
*
|
||||||
* <h2><center>© Copyright (c) 2016 STMicroelectronics.
|
* <h2><center>© 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)
|
||||||
{
|
{
|
||||||
|
|
12
src/userio.c
12
src/userio.c
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue