--- /dev/null
+dump
+logs
/***************************************************************************** */
/* 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;
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 */
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();
}
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);
} 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;
}
} 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 {
void board_io_config(void);
/* Configure external components */
-int external_config(uint32_t uart);
+int external_comp_config(uint32_t uart);
/***************************************************************************** */
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);
#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 */
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)
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 */
}
/* 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) {
/* 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.
/* 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)) {
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;
*************************************************************************** */
#include "core/system.h"
+#include "core/user_information_block.h"
+#include "core/iap.h"
#include "drivers/serial.h"
#include "drivers/ssp.h"
#include "lib/stdio.h"
#include "uSD.h"
+#include "time.h"
+#include "version.h"
/***************************************************************************** */
/* 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;
/* 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));
#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);