From: Nathael Pajani Date: Thu, 19 Nov 2020 18:55:48 +0000 (+0100) Subject: Scialys support going on ... X-Git-Url: http://git.techno-innov.fr/?a=commitdiff_plain;h=b81bc2c058947b82996c500afc62591453af4aa2;p=soft%2Flpc122x%2Fscialys Scialys support going on ... --- diff --git a/v10/.gitignore b/v10/.gitignore new file mode 100644 index 0000000..6361591 --- /dev/null +++ b/v10/.gitignore @@ -0,0 +1,2 @@ +dump +logs diff --git a/v10/config.c b/v10/config.c index fd10a18..864fc4f 100644 --- a/v10/config.c +++ b/v10/config.c @@ -217,6 +217,11 @@ void board_io_config(void) /***************************************************************************** */ /* Load or update user configuration from internal User Flash */ +/* The configuration is stored in the first user info page. + * The third one is used to store the "last used" uSD block only once per week + * in order to prevent deterioration of the flash block. This information is + * stored in the RTC RAM backed by the supercapa each time a new block is used. + */ struct scialys_config sc_conf; @@ -246,11 +251,6 @@ void read_internal_config(void) memset(&sc_conf, 0, sizeof(struct scialys_config)); uprintf(UART0, "User config read from flash has bad checksum.\n"); } - /* Config version error ? */ - if (sc_conf.conf_version != CONFIG_VERSION) { - sc_conf.config_ok = 0; - uprintf(UART0, "User config read from flash has bad config version : %d.\n", sc_conf.conf_version); - } } /* Update the board config in user flash */ @@ -364,12 +364,18 @@ void check_config(void) void read_scialys_main_config(void) { read_internal_config(); + /* Config version error ? */ + if (sc_conf.conf_version != CONFIG_VERSION) { + sc_conf.config_ok = 0; + uprintf(UART0, "User config read from flash has bad config version : %d.\n", + sc_conf.conf_version); + } /* Check that config read from flash is OK */ if (sc_conf.config_ok == CONFIG_OK) { uprintf(UART0, "Internal config read OK\n"); return; } - /* Check that it is up to date */ + /* Config is either blank or not up to date, update missing parts with defaults */ check_config(); } @@ -431,18 +437,19 @@ uint8_t interface_board_present = 0; uint8_t power_board_present = 0; -int external_config(uint32_t uart) +int external_comp_config(uint32_t uart) { int ret = 0; int retcode = 0; + /* RTC : must be done first to be able to access RTC RAM for uSD init */ + time_config(I2C0, RTC_ADDR); + time_init_check(uart); + /* uSD card */ uSD_config((struct pio *)&uSD_cs, SSP_BUS_0); uSD_detect(uart); - - /* RTC */ - time_config(I2C0, RTC_ADDR); - time_init_check(uart); + uSD_logs_init(uart); /* Thermocouple configuration */ max31855_sensor_config(&thermocouple); @@ -457,7 +464,7 @@ int external_config(uint32_t uart) } else { ret = tmp101_sensor_set_continuous_conversion(&tmp101_sensor_power); if (ret != 0) { - uprintf(uart, "Temp config error on power board: %d\n", ret); + uprintf(uart, "Temp config part 2 error on power board: %d\n", ret); power_board_present = 0; retcode -= 2; } @@ -472,7 +479,7 @@ int external_config(uint32_t uart) } else { ret = tmp101_sensor_set_continuous_conversion(&tmp101_sensor_display); if (ret != 0) { - uprintf(uart, "Temp config error on display board: %d\n", ret); + uprintf(uart, "Temp config part 2 error on display board: %d\n", ret); interface_board_present = 0; retcode -= 8; } else { diff --git a/v10/config.h b/v10/config.h index 2ef3e5c..3bea7e6 100644 --- a/v10/config.h +++ b/v10/config.h @@ -166,7 +166,7 @@ void modules_config(void); void board_io_config(void); /* Configure external components */ -int external_config(uint32_t uart); +int external_comp_config(uint32_t uart); /***************************************************************************** */ diff --git a/v10/interface.c b/v10/interface.c index c3da842..327789f 100644 --- a/v10/interface.c +++ b/v10/interface.c @@ -327,7 +327,6 @@ void config_interface_handle(void) break; case DATE_CONFIG: { static uint8_t date_idx = 0; - struct rtc_time now; snprintf(line, DISP_LLEN, "%c", 0x60); display_line(3, 6 + (date_idx * 3), line); rtc_pcf85363_time_read(&rtc_conf, &now); diff --git a/v10/main.c b/v10/main.c index 173a17e..1202dfb 100644 --- a/v10/main.c +++ b/v10/main.c @@ -53,18 +53,19 @@ #define OVERVOLTAGE_PROTECTION_CYCLES 100 -uint32_t forced_heater_mode = 0; +uint8_t forced_heater_mode = 0; /* flag */ uint32_t forced_heater_delay = 0; uint32_t forced_heater_time = 0; -uint8_t manual_forced_heater = 0; +uint8_t manual_forced_heater = 0; /* flag */ -uint8_t error_shutdown = 0; +uint8_t error_shutdown = 0; /* flag */ #define EXTERNAL_DISABLE_FORCE 0 /* Input is pulled low when external disable is ON */ -int external_disable = 0; -int temp_shutdown = 0; -int overvoltage = 0; +uint8_t external_disable = 0; +uint8_t temp_shutdown = 0; +uint8_t overvoltage = 0; /* Used to create a delay when overvoltage is detected, + set to OVERVOLTAGE_PROTECTION_CYCLES and decreases to 0 */ enum modes { heat = 'C', /* Normal heating */ @@ -190,8 +191,9 @@ volatile uint8_t command_val = 0; volatile int act_cmd = 0; /* Start off */ int8_t force_cmd = -1; /* Forced command value, for tests */ int8_t old_cmd = 0; /* Used to store cmd value when entering over-voltage protection mode */ -static int fan_on = 0; -int force_fan = 0; /* Request to force fan ON from test menu */ +#define FAN_CNT_START (15 * 1000) +static uint16_t fan_on = 0; +uint8_t force_fan = 0; /* Request to force fan ON from test menu */ void set_ctrl_duty_cycle(uint8_t value) @@ -374,11 +376,14 @@ cmd_update_limited_end: cmd_update_end: if ((cmd > 0) || (force_fan == 1)) { - fan_on = 1; + fan_on = FAN_CNT_START; gpio_set(fan_ctrl); } else { - fan_on = 0; - gpio_clear(fan_ctrl); + if (fan_on > 0) { + fan_on--; + } else { + gpio_clear(fan_ctrl); + } } //command_val = cmd; /* Set Control Output duty cycle */ @@ -428,16 +433,16 @@ void mode_update(uint32_t unused) } /* Do not force heating if disabled by external command */ - external_disable = gpio_read(ext_disable_in_pin); + external_disable = (gpio_read(ext_disable_in_pin) ? 1 : 0); if ((external_disable == EXTERNAL_DISABLE_FORCE) && (forced_heater_mode != 0)) { forced_heater_mode = 0; mode = ext_disable; msg = "Forced mode disabled by external input\n"; } /* Get Over-Voltage or Over-Temperature information */ - temp_shutdown = !gpio_read(overtemperature_pin); + temp_shutdown = (gpio_read(overtemperature_pin) ? 0 : 1); if (overvoltage > 0) { - uint32_t ov_tmp = gpio_read(overvoltage_pin); + uint8_t ov_tmp = (gpio_read(overvoltage_pin) ? 0 : 1); if (ov_tmp == 0) { overvoltage--; if (overvoltage == 0) { @@ -561,9 +566,10 @@ int main(void) /* Order is important here */ system_init(); + msleep(800); /* Required for uSD to stabilise before SPI is setup .... */ board_io_config(); modules_config(); - external_config(UART0); + external_comp_config(UART0); read_scialys_main_config(); /* Compute max_intensity from config grid_power_limit. @@ -638,7 +644,8 @@ int main(void) /* Display */ /* only update twice per second */ cur_tick = systick_get_tick_count(); - if (cur_tick < last_tick_update) { + if ((cur_tick < last_tick_update) || ((~0 - last_tick_update) < 500)) { + /* simple tick wrapping handling */ last_tick_update = 0; } if (cur_tick > (last_tick_update + 500)) { @@ -646,6 +653,43 @@ int main(void) last_tick_update = cur_tick; } + /* Store data on uSD once every N seconds. + * Note : Once every second requires about 1Go per year. + */ + #define NB_SEC_STORE 5 + if (1) { + static uint32_t last_tick_store = 0; + static struct sd_data_blob data; + static uint8_t nb_val = 0; + + if (nb_val == 0) { + memset(&data, 0, sizeof(struct sd_data_blob)); + } + /* simple tick wrapping handling */ + if ((cur_tick < last_tick_store) || ((~0 - last_tick_store) < (NB_SEC_STORE * 1000))) { + last_tick_store = 0; + } + + /* Each flag is set if seen once within the interval */ + data.flags |= (fan_on ? 1 : 0) | (force_fan << 1); + data.flags |= (error_shutdown << 2) | (temp_shutdown << 3) | (overvoltage << 4); + data.flags |= (external_disable << 5); + data.flags |= (forced_heater_mode << 6) | (manual_activation_request << 7); + + /* Add current value to the storage value */ + /* FIXME */ + nb_val++; + + if (cur_tick > (last_tick_store + (NB_SEC_STORE * 1000))) { + /* Divide by the number of values */ + /* FIXME */ + uSD_append_data(&data); + uprintf(UART0, "Saved 5s data\n"); + nb_val = 0; + last_tick_store = cur_tick; + } + } + /* Debug */ if (1) { external_disable |= linky_disable; diff --git a/v10/uSD.c b/v10/uSD.c index d9cc349..1801061 100644 --- a/v10/uSD.c +++ b/v10/uSD.c @@ -20,6 +20,8 @@ *************************************************************************** */ #include "core/system.h" +#include "core/user_information_block.h" +#include "core/iap.h" #include "drivers/serial.h" #include "drivers/ssp.h" @@ -27,6 +29,8 @@ #include "lib/stdio.h" #include "uSD.h" +#include "time.h" +#include "version.h" /***************************************************************************** */ @@ -40,66 +44,187 @@ static uint8_t got_uSD = 0; /* Buffer to read / write uSD card */ uint8_t mmc_data[MMC_BUF_SIZE]; +#define SCIALYS_MAGIC "Scialys data bloc" -/* Read up to 4 blocks of 16 bytes each */ -int uSD_read(uint32_t offset, uint8_t nb_blocks) +/* Read 1 block of 512 bytes */ +int uSD_read(uint32_t block_num) { - int i = 0, ret = 0; + int ret = 0; if (got_uSD == 0) { return -1; } - if (nb_blocks > 4) { - return -2; - } - memset(mmc_data, 0, MMC_BUF_SIZE); - for (i = 0; i < nb_blocks; i++) { - ret = sdmmc_read_block(µ_sd, (offset + i), (mmc_data + (i * 16))); - /* FIXME : check return value */ - } - return 0; + ret = sdmmc_read_block(µ_sd, block_num, mmc_data); + /* FIXME : check return value */ + return ret; } -/* Write up to 4 blocks of 16 bytes each */ -int uSD_write(uint32_t offset, uint8_t nb_blocks) +/* Write 1 block of 512 bytes */ +int uSD_write(uint32_t block_num) { - int i = 0, ret = 0; + int ret = 0; if (got_uSD == 0) { return -1; } - if (nb_blocks > 4) { + ret = sdmmc_write_block(µ_sd, block_num, mmc_data); + /* FIXME : check return value */ + return ret; +} + + +/* Setup the first part of a data buffer (a 512 bytes uSD block) */ +int uSD_init_buffer(void) +{ + int idx = 0; + memset((char*)mmc_data, 0, MMC_BUF_SIZE); + + /* Store magic to uSD data block head to mark as a valid data block */ + memcpy(mmc_data, SCIALYS_MAGIC, strlen(SCIALYS_MAGIC) + 1); + idx = strlen(SCIALYS_MAGIC) + 1; + + /* Add current version string */ + memcpy(mmc_data + idx, MODULE_VERSION_STR, strlen(MODULE_VERSION_STR) + 1); + idx += strlen(MODULE_VERSION_STR) + 1; + mmc_data[idx++] = SOFT_VERSION_STR[0]; + memcpy(mmc_data + idx, COMPILE_VERSION, strlen(COMPILE_VERSION) + 1); + idx += strlen(COMPILE_VERSION) + 1; + + /* Add date */ + memcpy(mmc_data + idx, (uint8_t*)&now, sizeof(struct rtc_time)); + idx += sizeof(struct rtc_time); + + return idx; +} + + +/* Check that the first part of a data buffer is a valid data block */ +int uSD_data_buffer_is_valid(void) +{ + return strncmp((char*)mmc_data, SCIALYS_MAGIC, strlen(SCIALYS_MAGIC)); +} + +/* Last used uSD block. Store new data on the next one */ +struct last_block_info { + uint32_t magic; + uint32_t block_num; +}; +#define LAST_BLOCK_MAGIC 0x4C415354 /* LAST in ascii, big endian */ +static struct last_block_info last_block = { + .magic = LAST_BLOCK_MAGIC, + .block_num = 1, +}; +#define LAST_BLOCK_INFO_OFFSET_IN_USER_FLASH (2 * 512) /* Use third page in user info block */ + + +/* Find last log entry (last used uSD block) */ +int uSD_logs_init(int uart) +{ + int idx = 0, ret = 0; + + /* First, check RAM from RTC to get last block used info */ + ret = rtc_pcf85363a_read_ram(&rtc_conf, 0, (uint8_t*)&last_block, sizeof(struct last_block_info)); + if (ret != 0) { + uprintf(uart, "Error when reading RAM from RTC : %d\n", ret); return -1; } - for (i = 0; i < nb_blocks; i++) { - ret = sdmmc_write_block(µ_sd, (offset + i), (mmc_data + (i * 16))); - /* FIXME : check return value */ + if (last_block.magic == LAST_BLOCK_MAGIC) { + /* Consider that the last block number is valid too :) */ + uprintf(uart, "Last block info from RAM : %d\n", last_block.block_num); + return 0; + } + /* Invalid magic in RTC RAM ... */ + uprintf(uart, "Last block info not valid in RAM\n"); + /* FIXME : read info at offset LAST_BLOCK_INFO_OFFSET_IN_USER_FLASH to get the last block used info */ + last_block.block_num = 1; + last_block.magic = LAST_BLOCK_MAGIC; + return 0; +} + + +int uSD_append_data(struct sd_data_blob* data) +{ + static uint16_t index = 0; + + if (index == 0) { + index = uSD_init_buffer(); + } + + /* Store data to buffer */ + memcpy(mmc_data + index, data, sizeof(struct sd_data_blob)); + index += sizeof(struct sd_data_blob); + + /* Flush buffer to uSD ? */ + if ((index + sizeof(struct sd_data_blob)) >= MMC_BUF_SIZE) { + int ret = uSD_write(last_block.block_num + 1); + if (ret != 0) { + uprintf(UART0, "Write to uSD returned %d\n", ret); + return ret; + } + last_block.block_num++; + /* Save block number to RTC RAM */ + rtc_pcf85363a_write_ram(&rtc_conf, 0, (uint8_t*)&last_block, sizeof(struct last_block_info)); + /* Store last used uSD block in flash once every 2048 blocks */ + if ((last_block.block_num & 0x3FF) == 0x00) { + /* FIXME */ + } + index = 0; + uprintf(UART0, "Wrote 512 bytes to SD card\n"); + return 1; } + return 0; } -/* microSD card init */ + +/***************************************************************************** */ +/* micro SD card init */ + + int uSD_detect(int uart) { - int i = 0, ret = 0, step = 0; + int i = 0, loop = 0, ret = 0; +#ifdef DEBUG + int step = 0; +#endif + + /* Issue a first CMD0 to get SD card to SPI mode */ + ret = sdmmc_reset(µ_sd); + + /* Let some time for uSD card to power up */ do { - step = 0; + i = 0; + msleep(250); ret = sdmmc_init(µ_sd); if (ret == 0) { +#ifdef DEBUG step = 1; - msleep(10); - ret = sdmmc_init_wait_card_ready(µ_sd); +#endif + do { + i++; + msleep(10); + ret = sdmmc_init_wait_card_ready(µ_sd); + } while ((ret == 0 ) && (i < 10)); if (ret <= 1) { +#ifdef DEBUG step = 2; +#endif ret = sdmmc_init_end(µ_sd); } } - uprintf(uart, "uSD init(%d): step:%d, ret: %d, type: %d, bs: %d\n", - i, step, ret, micro_sd.card_type, micro_sd.block_size); - i++; - } while (((ret != 0) || (micro_sd.card_type == MMC_CARDTYPE_UNKNOWN)) && (i < 10)); + if (micro_sd.card_type == MMC_CARDTYPE_UNKNOWN) { + uprintf(uart, "Unknown card type :(\n"); + } +#ifdef DEBUG + uprintf(uart, "uSD init(%d - %d): step:%d, ret: %d, type: %d, bs: %d\n", + loop, i, step, ret, micro_sd.card_type, micro_sd.block_size); +#endif + if (loop++ > 10) { + break; + } + } while ((loop < 2) || (((ret < 0) || (ret > 1)) && (micro_sd.card_type == MMC_CARDTYPE_UNKNOWN))); /* Got uSD ? */ - if (i >= 10) { + if (loop >= 10) { uprintf(uart, "uSD init failed, no uSD card present.\n"); got_uSD = 0; return -1; @@ -108,22 +233,13 @@ int uSD_detect(int uart) /* uSD card detected */ got_uSD = 1; /* got_uSD MUST be set to 1 from here on ! */ - uSD_read(0, 4); /* Read 4 blocks at start of card */ + ret = uSD_read(0); /* Read 1 block at start of card */ /* FIXME : check that the card magic is present */ - uprintf(uart, "uSD read: %s\n", mmc_data); + uprintf(uart, "uSD read (ret : %d) : %s\n", ret, mmc_data); return 0; } - -int uSD_logs_init(int uart) -{ - /* FIXME : read 4 blocks at offset FIXME to get the last block used info */ - return 0; -} - -/***************************************************************************** */ -/* microSD card init */ void uSD_config(struct pio* uSD_cs, uint32_t ssp_bus_num) { memcpy(&(micro_sd.chip_select), uSD_cs, sizeof(struct pio)); diff --git a/v10/uSD.h b/v10/uSD.h index ef4a764..c775ed4 100644 --- a/v10/uSD.h +++ b/v10/uSD.h @@ -24,16 +24,55 @@ #include "extdrv/sdmmc.h" -#define MMC_BUF_SIZE 64 + +/* A 512 bytes block stores 17 data blobs of 28 bytes with a header of up to 36 bytes */ +/* Header is : + * 18 bytes : SCIALYS_MAGIC : "Scialys data bloc" + * 6 bytes : MODULE_VERSION_STR : "v0.00" + * 4 bytes: SOFT_VERSION_STR : "T" or "P" + COMPILE_VERSION : "XX" + * 8 bytes : date + */ +#define MMC_BUF_SIZE 512 + +struct sd_data_blob { + uint32_t solar_prod_value; + uint32_t home_conso_value; + int water_centi_degrees; + int deci_degrees_power; + int deci_degrees_disp; + uint16_t load_power_lowest; + uint16_t load_power_highest; + uint8_t command_val; + uint8_t act_cmd; + uint8_t mode; + uint8_t flags; +} __attribute__ ((__packed__)); + +/* +struct flags { + uint8_t fan_on; + uint8_t force_fan; + uint8_t error_shutdown; + uint8_t temp_shutdown; + uint8_t overvoltage; + uint8_t external_disable; + uint8_t forced_heater_mode; + uint8_t manual_activation_request; +}; +*/ extern struct sdmmc_card micro_sd; extern uint8_t mmc_data[MMC_BUF_SIZE]; -int uSD_read(uint32_t offset, uint8_t nb_blocks); -int uSD_write(uint32_t offset, uint8_t nb_blocks); +int uSD_read(uint32_t block_num); +int uSD_write(uint32_t block_num); + +int uSD_append_data(struct sd_data_blob* data); + /***************************************************************************** */ /* microSD card init */ +int uSD_logs_init(int uart); int uSD_detect(int uart); void uSD_config(struct pio* uSD_cs, uint32_t ssp_bus_num);