Scialys support going on ...
authorNathael Pajani <nathael.pajani@ed3l.fr>
Thu, 19 Nov 2020 18:55:48 +0000 (19:55 +0100)
committerNathael Pajani <nathael.pajani@ed3l.fr>
Tue, 8 Nov 2022 11:07:29 +0000 (12:07 +0100)
v10/.gitignore [new file with mode: 0644]
v10/config.c
v10/config.h
v10/interface.c
v10/main.c
v10/uSD.c
v10/uSD.h

diff --git a/v10/.gitignore b/v10/.gitignore
new file mode 100644 (file)
index 0000000..6361591
--- /dev/null
@@ -0,0 +1,2 @@
+dump
+logs
index fd10a18..864fc4f 100644 (file)
@@ -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 {
index 2ef3e5c..3bea7e6 100644 (file)
@@ -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);
 
 
 /***************************************************************************** */
index c3da842..327789f 100644 (file)
@@ -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);
index 173a17e..1202dfb 100644 (file)
 #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;
index d9cc349..1801061 100644 (file)
--- 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(&micro_sd, (offset + i), (mmc_data + (i * 16)));
-               /* FIXME : check return value */
-       }
-       return 0;
+       ret = sdmmc_read_block(&micro_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(&micro_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(&micro_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(&micro_sd);
+
+       /* Let some time for uSD card to power up */
        do {
-               step = 0;
+               i = 0;
+               msleep(250);
                ret = sdmmc_init(&micro_sd);
                if (ret == 0) {
+#ifdef DEBUG
                        step = 1;
-                       msleep(10);
-                       ret = sdmmc_init_wait_card_ready(&micro_sd);
+#endif
+                       do {
+                               i++;
+                               msleep(10);
+                               ret = sdmmc_init_wait_card_ready(&micro_sd);
+                       } while ((ret == 0 ) && (i < 10));
                        if (ret <= 1) {
+#ifdef DEBUG
                                step = 2;
+#endif
                                ret = sdmmc_init_end(&micro_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));
index ef4a764..c775ed4 100644 (file)
--- a/v10/uSD.h
+++ b/v10/uSD.h
 
 #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);