nor_flash_integration_example

0 阅读7分钟

/*

  • Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.
  • Description: littlefs + NOR Flash + Log Manager Integration Example
  • This example demonstrates how to:
    1. Initialize external NOR Flash via SFC driver
    1. Mount littlefs on the NOR Flash
    1. Use log_manager for timestamp-based logging
    1. Monitor Flash storage status */

#include "sfc.h" #include "littlefs_adapt.h" #include "log_manager.h" #include "partition.h" #include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h>

// ==================== 常量定义 ====================

/**

  • NOR Flash 存储配置
  • 示例硬件配置:
    • Flash 芯片:GD25Q32(4MB)
    • 存储地址范围:0x200000 ~ 0x600000
    • 分区分配:
    • littlefs 分区:256KB(0x200000 ~ 0x240000)
    • 日志存储:3.5MB(用于日志文件)
    • 预留:200KB(边界和安全) */

#define NOR_FLASH_START_ADDR 0x200000 // NOR Flash 起始地址(外挂) #define LITTLEFS_PARTITION_SIZE 0x40000 // littlefs 分区大小(256KB) #define LOG_STORAGE_SIZE 0x380000 // 日志存储大小(3.5MB)

// ==================== 初始化函数 ====================

/**

  • @brief 初始化外挂 NOR Flash

  • 步骤:

    1. 配置 SFC(Serial Flash Controller)驱动参数
    1. 检测 Flash 芯片 ID,匹配相应配置(GD25Q32/W25Q32 等)
    1. 初始化 SFC 控制器
  • @return 0 成功,-1 失败 */ int init_nor_flash(void) { printf("\n=== Initializing NOR Flash (External) ===\n");

    // SFC 驱动配置 sfc_flash_config_t sfc_config = { .mapping_addr = NOR_FLASH_START_ADDR, // NOR Flash 物理地址 .mapping_size = 0x400000, // 支持的最大映射大小(4MB) .read_type = QUAD_READ, // 四线读(最快,~150MHz) .write_type = QUAD_PROGRAM // 四线编程 };

    // 初始化 SFC 驱动 errcode_t ret = uapi_sfc_init(&sfc_config); if (ret != ERRCODE_SUCC) { printf("ERROR: SFC initialization failed (code: 0x%X)\n", ret); return -1; }

    printf("✅ SFC driver initialized\n"); printf(" - Start Address: 0x%08X\n", NOR_FLASH_START_ADDR); printf(" - Mapping Size: %u KB\n", sfc_config.mapping_size / 1024); printf(" - Read Interface: QUAD SPI (150MHz)\n"); printf(" - Write Interface: QUAD Program\n");

    return 0; }

/**

  • @brief 初始化 littlefs 文件系统

  • 功能:

    • 通过 fs_adapt_mount() 挂载 NOR Flash 上的 littlefs
    • 自动格式化(如果尚未格式化)
    • 创建日志目录
  • @return 0 成功,-1 失败 */ int init_littlefs_on_nor_flash(void) { printf("\n=== Mounting littlefs on NOR Flash ===\n");

    // 挂载 littlefs(会自动检测和格式化) fs_adapt_mount();

    // 创建日志目录 int ret = fs_adapt_mkdir("/logs"); if (ret == LFS_ERR_OK || ret == LFS_ERR_EXIST) { printf("✅ littlefs mounted and /logs directory ready\n"); printf(" - Partition Start: 0x%08X\n", NOR_FLASH_START_ADDR); printf(" - Partition Size: %u KB\n", LITTLEFS_PARTITION_SIZE / 1024); return 0; } else { printf("ERROR: littlefs mount or mkdir failed (code: %d)\n", ret); return -1; } }

/**

  • @brief 完整的系统初始化

  • 初始化顺序:

    1. NOR Flash 硬件驱动
    1. littlefs 文件系统
    1. 日志管理系统
  • @return 0 成功,-1 失败 */ int system_init_complete(void) { printf("\n"); printf("╔════════════════════════════════════════╗\n"); printf("║ littlefs + NOR Flash + Log Manager ║\n"); printf("║ Integration Example ║\n"); printf("╚════════════════════════════════════════╝\n");

    // Step 1: Initialize NOR Flash if (init_nor_flash() != 0) { return -1; }

    // Step 2: Initialize littlefs if (init_littlefs_on_nor_flash() != 0) { return -1; }

    // Step 3: Initialize log manager if (log_manager_init() != 0) { printf("ERROR: Log manager initialization failed\n"); return -1; }

    printf("✅ Log manager initialized\n"); printf(" - Log Directory: /logs\n"); printf(" - Auto-Rotation: > 1MB\n"); printf(" - Max Files: 20\n");

    printf("\n✅ System initialization complete!\n");

    return 0; }

// ==================== 应用示例 ====================

/**

  • @brief 示例 1:系统启动日志记录 */ void example_startup_logging(void) { printf("\n=== Example: Startup Logging ===\n");

    log_manager_write_level("INFO", "═══════════════════════════════════"); log_manager_write_level("INFO", "System Startup with External NOR Flash"); log_manager_write_level("INFO", "═══════════════════════════════════");

    log_manager_printf("Firmware Version: v2.0.0 (NOR Flash Build)"); log_manager_printf("Build Time: %s %s", DATE, TIME);

    log_manager_write_level("DEBUG", "Initializing system components"); log_manager_write_level("INFO", "✓ NOR Flash initialized (GD25Q32 - 4MB)"); log_manager_write_level("INFO", "✓ littlefs mounted"); log_manager_write_level("INFO", "✓ Log manager ready");

    log_manager_write_level("INFO", "System ready for operation");

    printf("✅ Logged system startup\n"); }

/**

  • @brief 示例 2:定期传感器数据采集和记录

  • 模拟 IoT 设备生采集温湿度数据的场景 */ void example_sensor_data_logging(void) { printf("\n=== Example: Sensor Data Logging ===\n");

    log_manager_write_level("INFO", "Starting sensor monitoring (30 seconds)");

    // 模拟 30 秒的传感器数据采集 time_t start_time = time(NULL); int sample_count = 0;

    while (time(NULL) - start_time < 30 && sample_count < 50) { // 模拟传感器读取 int temperature = 20 + (rand() % 15); int humidity = 30 + (rand() % 50); float voltage = 4.2f - (rand() % 200) / 1000.0f;

     // 记录传感器数据
     log_manager_printf("SENSOR: T=%dC H=%d%% V=%.2fV Bat=OK", 
                       temperature, humidity, voltage);
     
     // 模拟周期性采样
     sleep(1);  // 每秒采样一次
     sample_count++;
    

    }

    printf("✅ Logged %d sensor samples\n", sample_count); }

/**

  • @brief 示例 3:监控 Flash 存储和日志文件 */ void example_storage_monitoring(void) { printf("\n=== Example: Storage Monitoring ===\n");

    // 获取 Flash 存储信息 unsigned int start_addr, total_size, free_size; if (log_manager_get_flash_info(&start_addr, &total_size, &free_size) != 0) { printf("ERROR: Failed to get flash info\n"); return; }

    // 计算统计信息 unsigned int used_size = total_size - free_size; float usage_percent = (100.0f * used_size) / total_size;

    // 显示 Flash 状态 printf("Flash Memory Status:\n"); printf(" Start Address: 0x%08X\n", start_addr); printf(" Total Size: %u B (%.2f KB, %.2f MB)\n", total_size, total_size/1024.0f, total_size/(1024.0f1024.0f)); printf(" Used Size: %u B (%.2f KB, %.2f MB, %.1f%%)\n", used_size, used_size/1024.0f, used_size/(1024.0f1024.0f), usage_percent); printf(" Free Size: %u B (%.2f KB, %.2f MB, %.1f%%)\n", free_size, free_size/1024.0f, free_size/(1024.0f*1024.0f), 100.0f - usage_percent);

    // 显示日志文件统计 log_file_info_t files[20]; int count = 0; if (log_manager_list_files(files, 20, &count) == 0) { printf("\nLog Files (%d files):\n", count); for (int i = 0; i < count; i++) { printf(" [%d] %s - %u B (%.2f KB)\n", i+1, files[i].filename, files[i].size, files[i].size/1024.0f); } }

    // 显示存储容量预告 unsigned int avg_file_size = 50 * 1024; // 假设 50KB 每个文件 unsigned int estimated_files = free_size / avg_file_size; printf("\nEstimation:\n"); printf(" Can store ~%u more log files (avg 50KB each)\n", estimated_files > 0 ? estimated_files : 1);

    // 显示预警 if (usage_percent > 90.0f) { printf(" ⚠️ WARNING: Storage is >90%% full!\n"); log_manager_write_level("WARN", "Flash storage usage exceeds 90%% - cleanup recommended"); } else if (usage_percent > 70.0f) { printf(" ℹ️ INFO: Storage usage is 70-90%%\n"); } }

/**

  • @brief 示例 4:持久化日志数据(读取和导出) */ void example_log_persistence(void) { printf("\n=== Example: Log Data Persistence ===\n");

    // 获取当前日志文件 log_file_info_t current_file; if (log_manager_get_current_file_info(&current_file) != 0) { printf("ERROR: Failed to get current file info\n"); return; }

    printf("Current Log File: %s\n", current_file.filename); printf("Current File Size: %u B\n\n", current_file.size);

    // 读取日志内容(模拟导出到串口) const char *filename = strrchr(current_file.filename, '/') + 1; char log_buffer[2048];

    int bytes_read = log_manager_read(filename, log_buffer, sizeof(log_buffer)); if (bytes_read > 0) { printf("Log Content Preview (first 2KB):\n"); printf("──────────────────────────────────────\n"); printf("%s", log_buffer); printf("──────────────────────────────────────\n"); printf("Total bytes read: %d\n", bytes_read); } else { printf("No log data available\n"); } }

/**

  • @brief 示例 5:日志文件自动轮转演示

  • 当日志文件超过 1MB 时自动创建新文件 */ void example_log_rotation(void) { printf("\n=== Example: Log File Auto-Rotation ===\n"); printf("Writing large amount of data to trigger rotation...\n");

    log_file_info_t files_before[20]; int count_before = 0; log_manager_list_files(files_before, 20, &count_before);

    // 写入大量数据 for (int i = 0; i < 200; i++) { log_manager_printf("Data Block #%d: Lorem ipsum dolor sit amet, consectetur adipiscing elit. " "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", i);

     if (i % 50 == 0) {
         printf("  Wrote %d blocks...\n", i + 1);
     }
    

    }

    // 检查文件轮转 log_file_info_t files_after[20]; int count_after = 0; log_manager_list_files(files_after, 20, &count_after);

    printf("\nRotation Status:\n"); printf(" Files before: %d\n", count_before); printf(" Files after: %d\n", count_after); printf(" New files created: %d\n", count_after - count_before); }

/**

  • @brief 示例 6:错误处理和恢复演示 */ void example_error_handling(void) { printf("\n=== Example: Error Handling & Recovery ===\n");

    log_manager_write_level("INFO", "Starting error handling demonstration");

    // 模拟各种错误情况 log_manager_write_level("WARN", "Simulated warning: Temperature sensor reading inconsistent"); log_manager_write_level("ERROR", "Simulated error: WiFi connection lost"); log_manager_write_level("INFO", "Attempting to reconnect..."); log_manager_write_level("INFO", "WiFi reconnection successful"); log_manager_write_level("DEBUG", "Debug: Network stack reinitialized");

    printf("✅ Logged error scenarios\n"); }

// ==================== 主程序 ====================

int main(void) { printf("\n"); printf("╔════════════════════════════════════════════════════╗\n"); printf("║ System Architecture: NOR Flash + littlefs + Log ║\n"); printf("║ ║\n"); printf("║ Hardware: WS63 MCU + GD25Q32 (4MB) NOR Flash ║\n"); printf("║ Storage: 256KB littlefs + 3.5MB Log Files ║\n"); printf("╚════════════════════════════════════════════════════╝\n");

// 初始化系统
if (system_init_complete() != 0) {
    printf("\n❌ System initialization failed!\n");
    return -1;
}

// 运行示例
printf("\n\n");
printf("═══════════════════════════════════════════════════════\n");
printf("Running Integration Examples\n");
printf("═══════════════════════════════════════════════════════\n");

example_startup_logging();
example_sensor_data_logging();
example_storage_monitoring();
example_log_persistence();
example_log_rotation();
example_error_handling();

// 最终统计
printf("\n\n");
printf("═══════════════════════════════════════════════════════\n");
printf("Final Statistics\n");
printf("═══════════════════════════════════════════════════════\n");

log_file_info_t all_files[20];
int total_files = 0;
log_manager_list_files(all_files, 20, &total_files);

unsigned int total_log_size = 0;
for (int i = 0; i < total_files; i++) {
    total_log_size += all_files[i].size;
}

printf("Total Log Files: %d\n", total_files);
printf("Total Log Size: %u B (%.2f KB, %.2f MB)\n", 
       total_log_size, total_log_size/1024.0f, total_log_size/(1024.0f*1024.0f));

unsigned int flash_start, flash_total, flash_free;
log_manager_get_flash_info(&flash_start, &flash_total, &flash_free);
printf("Flash Usage: %.1f%% (%u B / %u B)\n", 
       100.0f * (flash_total - flash_free) / flash_total,
       flash_total - flash_free, flash_total);

// 清理
log_manager_cleanup();
fs_adapt_unmount();

printf("\n✅ All examples completed successfully!\n");
printf("\nSystem shutdown gracefully.\n");

return 0;

}