From d33cc2f77598956bfc1504ea70a358facc77bd8a Mon Sep 17 00:00:00 2001 From: true Date: Tue, 15 Oct 2024 04:23:00 -0700 Subject: [PATCH] add eeprom support, user config loading --- nametag8_CH592/user/comm/i2c.h | 7 ++- nametag8_CH592/user/comm/soft_i2c_master.c | 6 +-- nametag8_CH592/user/global.h | 5 +++ nametag8_CH592/user/hw/eeprom16.c | 52 +++++++++++++++++++++- nametag8_CH592/user/hw/eeprom16.h | 16 +++++++ nametag8_CH592/user/main.c | 51 ++++++++++++++++----- nametag8_CH592/user/user_config.c | 40 ++++++++++------- 7 files changed, 144 insertions(+), 33 deletions(-) diff --git a/nametag8_CH592/user/comm/i2c.h b/nametag8_CH592/user/comm/i2c.h index 60d8050..4476725 100644 --- a/nametag8_CH592/user/comm/i2c.h +++ b/nametag8_CH592/user/comm/i2c.h @@ -10,6 +10,9 @@ +#include "global.h" + + #ifdef SOFT_I2C_MASTER @@ -17,9 +20,9 @@ #define i2c_init() i2cm_init() -#define i2c_start() SetSysClock(CLK_SOURCE_PLL_32MHz); i2cm_start() +#define i2c_start() SetSysClock(SYSCLK_FREQ_USEI2C); i2cm_start() #define i2c_restart() i2cm_restart() -#define i2c_stop() SetSysClock(CLK_SOURCE_HSE_16MHz); i2cm_stop() +#define i2c_stop() SetSysClock(SYSCLK_FREQ_NORMAL); i2cm_stop() #define i2c_rd(ack) i2cm_rd(ack) #define i2c_wr(dat) i2cm_wr(dat) #define i2c_addr(a, w) i2c_start(); i2cm_addr(a, w) diff --git a/nametag8_CH592/user/comm/soft_i2c_master.c b/nametag8_CH592/user/comm/soft_i2c_master.c index 5d69c9c..6881c35 100644 --- a/nametag8_CH592/user/comm/soft_i2c_master.c +++ b/nametag8_CH592/user/comm/soft_i2c_master.c @@ -123,7 +123,7 @@ uint8_t i2cm_wr(uint8_t dat) for (x = 8; x; x--) { if (dat & 0x80) { SDA_IN_HI(); SCL_IN_HI(); wr_delay_hi(); } - else { SDA_OUTLO(); SCL_OUTLO(); wr_delay_lo(); } + else { SDA_OUTLO(); SCL_OUTLO(); wr_delay_lo(); } dat <<= 1; SCL_OUTLO(); @@ -149,7 +149,7 @@ uint8_t i2cm_addr(uint8_t addr, uint8_t reading_bit) void i2cm_rdbuf(uint8_t *dat, uint8_t len) { - while(len--) *dat++ = i2cm_rd(len > 0); + while (len--) *dat++ = i2cm_rd(len > 0); // i2cm_stop(); } @@ -157,7 +157,7 @@ void i2cm_wrbuf(const uint8_t *dat, uint8_t len) { uint8_t nack; - while(len--) { + while (len--) { nack = i2cm_wr(*dat++); if (nack) break; } diff --git a/nametag8_CH592/user/global.h b/nametag8_CH592/user/global.h index 97e1f59..873c2a8 100644 --- a/nametag8_CH592/user/global.h +++ b/nametag8_CH592/user/global.h @@ -12,6 +12,11 @@ +#define SYSCLK_FREQ_NORMAL CLK_SOURCE_HSE_16MHz +#define SYSCLK_FREQ_USEI2C CLK_SOURCE_PLL_32MHz + + + extern const uint8_t vers[]; extern uint8_t cpu_use; diff --git a/nametag8_CH592/user/hw/eeprom16.c b/nametag8_CH592/user/hw/eeprom16.c index b45da0e..d8c906f 100644 --- a/nametag8_CH592/user/hw/eeprom16.c +++ b/nametag8_CH592/user/hw/eeprom16.c @@ -1,8 +1,56 @@ /* * eeprom16.c * - * Created on: Oct 11, 2024 - * Author: true + * code to interface with 16-bit addressed I2C EEPROMs + * tested up to max size of 512Kbit (64Kbyte) + * */ +#include "eeprom16.h" +#include "comm/i2c.h" + + +uint8_t e16_read_byte(uint16_t addr) +{ + return 0; +} + +void e16_read(uint16_t addr, uint8_t *dat, uint32_t len) +{ + if (len > EEPROM_SIZE) return; + + i2c_start(); + i2c_addr(EEPROM_I2C_ADDR, 0); + i2c_wr(addr >> 8); + i2c_wr(addr & 0xff); + i2c_restart(); + i2c_addr(EEPROM_I2C_ADDR, 1); + + while (len--) *dat++ = i2cm_rd(len > 0); + + i2c_stop(); +} + +void e16_write(uint16_t addr, uint8_t *dat, uint16_t len) +{ + uint8_t nack; + + // this function can only write one page at a time + if (len > EEPROM_PAGE_SIZE) return; + + // this function does not detect page boundaries. + // it is your responsibility to correctly address for + // page boundaries. most eeprom roll over page boundaries. + + i2c_start(); + i2c_addr(EEPROM_I2C_ADDR, 0); + i2c_wr(addr >> 8); + i2c_wr(addr & 0xff); + + while (len--) { + nack = i2cm_wr(*dat++); + if (nack) break; + } +} + diff --git a/nametag8_CH592/user/hw/eeprom16.h b/nametag8_CH592/user/hw/eeprom16.h index 7d928be..fb40c6c 100644 --- a/nametag8_CH592/user/hw/eeprom16.h +++ b/nametag8_CH592/user/hw/eeprom16.h @@ -10,4 +10,20 @@ +#include + + + +#define EEPROM_I2C_ADDR 0xa0 + +#define EEPROM_SIZE 65536 +#define EEPROM_PAGE_SIZE 128 + + + +void e16_read(uint16_t addr, uint8_t *dat, uint32_t len); +void e16_write(uint16_t addr, uint8_t *dat, uint16_t len); + + + #endif /* USER_DEVICE_EEPROM16_H_ */ diff --git a/nametag8_CH592/user/main.c b/nametag8_CH592/user/main.c index 22a4a33..d90e14f 100644 --- a/nametag8_CH592/user/main.c +++ b/nametag8_CH592/user/main.c @@ -26,14 +26,33 @@ #include #include "CH59x_common.h" -#include "port_intr.h" - #include "comm/i2c.h" #include "hw/gat/gat_gpio.h" #include "led/rgbled.h" +#include "misc/accel.h" + +#include "global.h" +#include "port_intr.h" +#include "user_config.h" + + + +const uint8_t vers[] = "241013.01"; + +uint8_t cpu_use = 0; +uint8_t cpu_max = 0; + +uint32_t uptime = 0; +uint16_t uptime_hour; +uint8_t uptime_min; +uint8_t uptime_sec; + +uint32_t idle_time_menu; +uint32_t idle_time_still; +uint8_t idle_go_sleep; @@ -47,33 +66,43 @@ int main() { // configure clock ch59x_xtal_conf(); - SetSysClock(CLK_SOURCE_PLL_32MHz); + SetSysClock(SYSCLK_FREQ_USEI2C); // enable DC-DC converter; brings significant power saving PWR_DCDCCfg(ENABLE); - // get i2c up and running + // get i2c initialized since most stuff will need it i2c_init(); - // decrease clock speed when not using i2c - SetSysClock(CLK_SOURCE_HSE_16MHz); + // read the user config + uconf_load(); - // configure port-based interrupts (used for chsub interrupt, mainly) - port_intr_init(); - - // configure aux MCU initial settings, attention interrupt + // initialize aux MCU ch32sub_init(); // and enable RGBLED controller hardware pin so the controller can wake up + ch32sub_rgb_hwen(1); - // configure RGBLED controller + // initialize accelerometer + accel_init(); + + // initialize RGBLED controller rgbled_init(); // configure GAT aux GPIOs, get gat ID gat_gpio_init(); // configure GAT i2c slave + // not yet implemented + + // configure port-based interrupts (used for ch32sub interrupt) + port_intr_init(); + + // note that system clock speed is decreased after every use of I2C while(1) { // only care about aux MCU when all other processing is done ch32sub_process(); + + // sleep when we're doing nothing + __WFI(); } } diff --git a/nametag8_CH592/user/user_config.c b/nametag8_CH592/user/user_config.c index 38936fc..f9b121a 100644 --- a/nametag8_CH592/user/user_config.c +++ b/nametag8_CH592/user/user_config.c @@ -73,14 +73,14 @@ static void uconf_defaults() static int8_t uconf_validate() { + // blank check + if (uconf.checksum == 0xffff) return -1; + // version check if (uconf.ver != UCONF_VER) { - return -1; + return -2; } - // blank check - if (uconf.checksum == 0xffff) return -2; - // checksum verify if (!checksum_verify((uint8_t *)&uconf, sizeof(uconf) - 2, uconf.checksum)) { return -3; @@ -96,20 +96,16 @@ void uconf_load() { uint8_t i; - w25q_power_up(); - for (i = 0; i < FLASH_RSVD_PAGES; i++) { // find last page of valid config from flash uconf_flash_offset = (FLASH_RSVD_PAGES - 1) - i; - w25q_read(uconf_flash_offset * FLASH_UCONF_BYTES, (uint8_t *)&uconf, FLASH_UCONF_BYTES); + e16_read(uconf_flash_offset * FLASH_UCONF_BYTES, (uint8_t *)&uconf, FLASH_UCONF_BYTES); if (!uconf_validate()) { // valid data return; } } - w25q_power_down(); - // flash has no valid data whatsoever // don't worry about flash setup; that is done during writing uconf_flash_offset = 0xf0; @@ -118,16 +114,22 @@ void uconf_load() void uconf_write() { - eclic_global_interrupt_disable(); + uint32_t intr; - w25q_power_up(); + uint16_t fsize; + uint16_t faddr; + uint8_t *uaddr; + + + SYS_DisableAllIrq(&intr); // track writes and set up next page to write uconf.iter++; uconf_flash_offset++; if (uconf_flash_offset >= FLASH_RSVD_PAGES) { // we need to erase flash and start writing at the beginning - w25q_erase_sector(0x000000, 1); + // w25q_erase_sector(0x000000, 1); + uconf_flash_offset = 0; } @@ -135,9 +137,17 @@ void uconf_write() uconf.checksum = checksum_gen((uint8_t *)&uconf, sizeof(uconf) - 2); // write config data - w25q_write(uconf_flash_offset * FLASH_UCONF_BYTES, (uint8_t *)&uconf, FLASH_UCONF_BYTES); + fsize = FLASH_UCONF_BYTES; + faddr = uconf_flash_offset * FLASH_UCONF_BYTES; + uaddr = (uint8_t *)&uconf; - w25q_power_down(); + while (fsize) { + e16_write(faddr, uaddr, (fsize > 128) ? 128 : fsize); + if (fsize < 128) break; + fsize -= 128; + faddr += 128; + uaddr += 128; + } - eclic_global_interrupt_enable(); + SYS_RecoverIrq(intr); }