FluxDC/components/FluxSD/FluxSD.c

386 lines
11 KiB
C
Raw Normal View History

/**
* @file FluxSD.c
* @brief SD卡源文件
*
*
*
* @author wang xiang en
* @date 2025-04-18
* @version
* @copyright (C)2025, YUWELL MEDTECH Co.ltd
2025-03-07 19:07:31 +08:00
*/
#include "FluxSD.h"
/* 用于信息存储的SD卡结构体 */
struct SD_Data sdData;
/* SD卡配置 */
2025-03-15 09:37:07 +08:00
const static char *SD_TAG = "SD_TEST";
2025-03-07 19:07:31 +08:00
const char* names[] = {"CLK", "CMD", "D0", "D1", "D2", "D3"};
const int pins[] = {CONFIG_EXAMPLE_PIN_CLK,
CONFIG_EXAMPLE_PIN_CMD,
CONFIG_EXAMPLE_PIN_D0,
CONFIG_EXAMPLE_PIN_D1,
CONFIG_EXAMPLE_PIN_D2,
CONFIG_EXAMPLE_PIN_D3
};
const int pin_count = sizeof(pins)/sizeof(pins[0]);
pin_configuration_t config = {
.names = names,
.pins = pins,
};
/**
* @brief SD引脚状态改变
*
* SD卡引脚检测子函数
*
* @param[in] i
* @param[in] level
* @param[in] timeout
* @return
*/
2025-03-07 19:07:31 +08:00
static uint32_t get_cycles_until_pin_level(int i, int level, int timeout) {
uint32_t start = esp_cpu_get_cycle_count();
while(gpio_get_level(i) == !level && esp_cpu_get_cycle_count() - start < timeout) {
;
}
uint32_t end = esp_cpu_get_cycle_count();
return end - start;
}
/**
* @brief SD卡引脚检测
*
* SD卡引脚驱动能力及配置情况
*
* @param[in] config
* @param[in] pin_count
*/
static void check_sd_card_pins(pin_configuration_t *config, const int pin_count)
2025-03-07 19:07:31 +08:00
{
2025-03-15 09:37:07 +08:00
ESP_LOGI(SD_TAG, "Testing SD pin connections and pullup strength");
2025-03-07 19:07:31 +08:00
gpio_config_t io_conf = {};
for (int i = 0; i < pin_count; ++i) {
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_INPUT_OUTPUT_OD;
io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL(config->pins[i]);
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 0;
gpio_config(&io_conf);
}
printf("\n**** PIN recovery time ****\n\n");
for (int i = 0; i < pin_count; ++i) {
gpio_set_direction(config->pins[i], GPIO_MODE_INPUT_OUTPUT_OD);
gpio_set_level(config->pins[i], 0);
usleep(100);
gpio_set_level(config->pins[i], 1);
uint32_t cycles = get_cycles_until_pin_level(config->pins[i], 1, 10000);
printf("PIN %2d %3s %"PRIu32" cycles\n", config->pins[i], config->names[i], cycles);
}
printf("\n**** PIN recovery time with weak pullup ****\n\n");
for (int i = 0; i < pin_count; ++i) {
gpio_set_direction(config->pins[i], GPIO_MODE_INPUT_OUTPUT_OD);
gpio_pullup_en(config->pins[i]);
gpio_set_level(config->pins[i], 0);
usleep(100);
gpio_set_level(config->pins[i], 1);
uint32_t cycles = get_cycles_until_pin_level(config->pins[i], 1, 10000);
printf("PIN %2d %3s %"PRIu32" cycles\n", config->pins[i], config->names[i], cycles);
gpio_pullup_dis(config->pins[i]);
}
}
/**
* @brief SD卡写测试
*
*
*
* @param[in] path
* @param[in] data
*/
2025-03-07 19:07:31 +08:00
static esp_err_t s_example_write_file(const char *path, char *data)
{
2025-03-15 09:37:07 +08:00
ESP_LOGI(SD_TAG, "Opening file %s", path);
FILE *f = fopen(path, "a");
2025-03-07 19:07:31 +08:00
if (f == NULL) {
2025-03-15 09:37:07 +08:00
ESP_LOGE(SD_TAG, "Failed to open file for writing");
2025-03-07 19:07:31 +08:00
return ESP_FAIL;
}
fprintf(f, data);
fclose(f);
2025-03-15 09:37:07 +08:00
ESP_LOGI(SD_TAG, "File written");
2025-03-07 19:07:31 +08:00
return ESP_OK;
}
/**
* @brief SD卡中写入日志
*
*
*
* @param[in] data
2025-04-28 17:49:47 +08:00
* @param[in] file_name
* @param[in] functionName
* @param[in] taskName
* @param[in] line_num
* @param[in] freeStack
* @return 0
*/
2025-04-27 14:46:47 +08:00
esp_err_t example_write_log(char *data,char *file_name,char *functionName,char *taskName,uint16_t line_num,int32_t freeStack)
{
FILE *f = fopen(sdData.log_file_dir, "a+");
if (f == NULL) {
ESP_LOGE(SD_TAG, "Failed to open file for writing");
return ESP_FAIL;
}
2025-04-27 14:46:47 +08:00
fprintf(f, "%s,%s,%s,%s,%d,%ld,%s\n",\
sdData.strftime_buf,\
2025-04-25 08:19:43 +08:00
file_name,\
2025-04-27 14:46:47 +08:00
functionName,\
taskName,\
2025-04-25 08:19:43 +08:00
line_num,\
2025-04-27 14:46:47 +08:00
freeStack,\
2025-04-25 08:19:43 +08:00
data
);
fclose(f);
ESP_LOGI(SD_TAG, "File written to log file %s",sdData.log_file_dir);
return ESP_OK;
}
/**
* @brief SD卡读测试
*
*
*
* @param[in] path
*/
2025-03-07 19:07:31 +08:00
static esp_err_t s_example_read_file(const char *path)
{
2025-03-15 09:37:07 +08:00
ESP_LOGI(SD_TAG, "Reading file %s", path);
/* 创建文件控制句柄 */
2025-03-07 19:07:31 +08:00
FILE *f = fopen(path, "r");
if (f == NULL) {
2025-03-15 09:37:07 +08:00
ESP_LOGE(SD_TAG, "Failed to open file for reading");
2025-03-07 19:07:31 +08:00
return ESP_FAIL;
}
2025-03-07 19:07:31 +08:00
char line[EXAMPLE_MAX_CHAR_SIZE];
fgets(line, sizeof(line), f);//整行读取
//fread(line, sizeof(line), f);
2025-03-07 19:07:31 +08:00
fclose(f);
// strip newline
char *pos = strchr(line, '\n');
if (pos) {
*pos = '\0';
}
2025-03-15 09:37:07 +08:00
ESP_LOGI(SD_TAG, "Read from file: '%s'", line);
2025-03-07 19:07:31 +08:00
return ESP_OK;
}
/**
* @brief SD卡初始化
*
* SD读写总线
*
*/
2025-03-07 19:07:31 +08:00
void flux_sd_init(void)
{
esp_err_t ret;
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
2025-03-08 14:45:49 +08:00
.format_if_mount_failed = true,
2025-03-07 19:07:31 +08:00
.max_files = 5,
.allocation_unit_size = 16 * 1024
};
/* 初始化SD卡 */
2025-03-07 19:07:31 +08:00
sdmmc_card_t *card;
const char mount_point[] = MOUNT_POINT;
2025-03-15 09:37:07 +08:00
ESP_LOGI(SD_TAG, "Initializing SD card");
2025-03-07 19:07:31 +08:00
2025-03-15 09:37:07 +08:00
ESP_LOGI(SD_TAG, "Using SDMMC peripheral");
2025-03-07 19:07:31 +08:00
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
slot_config.width = 4;
slot_config.clk = CONFIG_EXAMPLE_PIN_CLK;
slot_config.cmd = CONFIG_EXAMPLE_PIN_CMD;
slot_config.d0 = CONFIG_EXAMPLE_PIN_D0;
slot_config.d1 = CONFIG_EXAMPLE_PIN_D1;
slot_config.d2 = CONFIG_EXAMPLE_PIN_D2;
slot_config.d3 = CONFIG_EXAMPLE_PIN_D3;
slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP;
2025-03-15 09:37:07 +08:00
ESP_LOGI(SD_TAG, "Mounting filesystem");
2025-03-07 19:07:31 +08:00
ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, &card);
if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
2025-03-15 09:37:07 +08:00
ESP_LOGE(SD_TAG, "Failed to mount filesystem. "
2025-03-07 19:07:31 +08:00
"If you want the card to be formatted, set the EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
} else {
2025-03-15 09:37:07 +08:00
ESP_LOGE(SD_TAG, "Failed to initialize the card (%s). "
2025-03-07 19:07:31 +08:00
"Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
check_sd_card_pins(&config, pin_count);
}
return;
}
2025-03-15 09:37:07 +08:00
ESP_LOGI(SD_TAG, "Filesystem mounted");
/* 打印SD卡信息 */
2025-03-07 19:07:31 +08:00
sdmmc_card_print_info(stdout, card);
}
/**
* @brief
*
* 1.
*
*
* 2.
*/
esp_err_t sd_current_fileIndex_get(void)
{
/* 读取当前文件索引值 */
ESP_LOGI(SD_TAG, "Opening file %s", INDEX_FILE_NAME);
/* 判断文件是否存在 */
if (access(INDEX_FILE_NAME, F_OK) == -1)
{
/*当文件不存在时创建文件*/
FILE *new_f = fopen(INDEX_FILE_NAME, "w");
fprintf(new_f, "0");
fclose(new_f);
sdData.file_index = 0;
ESP_LOGI(SD_TAG, "File not found, creating new file");
}else{
/* 当文件存在时直接获取当前索引值 */
FILE *f = fopen(INDEX_FILE_NAME, "r");
if (f == NULL) {
ESP_LOGE(SD_TAG, "Failed to open file for reading");
return ESP_FAIL;
}
char line[EXAMPLE_MAX_CHAR_SIZE];
fgets(line, sizeof(line), f);
fclose(f);
sdData.file_index = atoi(line);
ESP_LOGI(SD_TAG, "Read from file: '%s' , current Index = %d", line,sdData.file_index);
}
/* 重置索引值 */
FILE *new_index_f = fopen(INDEX_FILE_NAME, "w");
if (new_index_f == NULL)
{
return ESP_FAIL;
}
fprintf(new_index_f, "%d", sdData.file_index+1);
fclose(new_index_f);
return ESP_OK;
}
/**
* @brief SD卡中写入测试结果
*
* 1.
* 2.
*/
2025-04-23 16:00:26 +08:00
esp_err_t sd_testData_write(bool is_nom,float test_result)
{
2025-04-23 16:00:26 +08:00
if (is_test_mode_nom)
{
2025-04-23 16:00:26 +08:00
/* 获取当前挡位及呼吸频率 */
int32_t current_stage = lv_spinbox_get_value(ui_pageHome_spinboxStage);
int32_t current_rate = lv_spinbox_get_value(ui_pageHome_spinboxRate);
/* 打开当前测试文件 */
FILE *current_test_f = fopen(sdData.test_file_dir, "a+");
if (current_test_f == NULL)
{
ESP_LOGE(SD_TAG, "Failed to open file for writing");
return ESP_FAIL;
}
fprintf(current_test_f,"%lld,%s,%d,%d,%ld,%ld,%.3f\n",\
sdData.current_time,\
sdData.strftime_buf,\
is_nom,\
sdData.flux_test_result.current_device_type,\
current_stage,\
current_rate,\
test_result
);
fclose(current_test_f);
/* 打开总的测试结果文件 */
FILE *total_test_f = fopen(TEST_FILE_NAME, "a+");
if (total_test_f == NULL)
{
ESP_LOGE(SD_TAG, "Failed to open file for writing");
return ESP_FAIL;
}
2025-04-23 16:00:26 +08:00
fprintf(total_test_f,"%lld,%s,%d,%d,%ld,%ld,%.3f\n",\
sdData.current_time,\
sdData.strftime_buf,\
is_nom,\
sdData.flux_test_result.current_device_type,\
current_stage,\
current_rate,\
test_result
);
fclose(total_test_f);
}
return ESP_OK;
2025-04-25 08:19:43 +08:00
}
/**
* @brief
*
* 1.
* 2.
*/
void sd_append_bs_data(void)
{
/* 打开bs测试结果文件 */
FILE *bs_test_f = fopen(sdData.bs_file_dir, "a+");
if (bs_test_f == NULL)
{
ESP_LOGE(SD_TAG, "Failed to open file for writing");
return;
}
fprintf(bs_test_f,"%lld,%s,%d,%ld,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f\n",\
sdData.current_time,\
sdData.strftime_buf,\
lv_dropdown_get_selected(ui_pageHome_DropdownTestTypeBS),\
lv_spinbox_get_value(ui_pageHome_spinboxStageBS),\
sdData.flux_test_result.test_result[BS_RATE_15BPM],\
sdData.flux_test_result.test_result[BS_RATE_20BPM],\
sdData.flux_test_result.test_result[BS_RATE_25BPM],\
sdData.flux_test_result.test_result[BS_RATE_30BPM],\
sdData.flux_test_result.test_result[BS_RATE_35BPM],\
sdData.flux_test_result.test_result[BS_RATE_40BPM]
);
fclose(bs_test_f);
2025-03-15 09:37:07 +08:00
}