add eeprom support, user config loading

This commit is contained in:
true 2024-10-15 04:23:00 -07:00
parent 6a4284176b
commit d33cc2f775
7 changed files with 144 additions and 33 deletions

View File

@ -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)

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -10,4 +10,20 @@
#include <stdint.h>
#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_ */

View File

@ -26,14 +26,33 @@
#include <hw/ch32sub.h>
#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();
}
}

View File

@ -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);
}