프로젝트 정리: 미사용 파일 삭제

This commit is contained in:
2026-04-15 12:01:03 +09:00
parent 82d3787b8a
commit 82b6be9205
8 changed files with 142 additions and 1131 deletions

View File

@@ -1 +0,0 @@
void battery_level_meas(void);

View File

@@ -1,105 +0,0 @@
/*
* dr_lua.c
*
* Author : Charles KWON
*
* This module provides a simple and reusable interface layer
* between C firmware code and embedded Lua scripts.
* It is designed to make calling Lua functions from C firmware
* straightforward and safe.
*
* Example:
* Lua function: add3(x) = x + 3
* C function : dr_lua_add3(int num1)
*/
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
/* -------------------------------------------------
* External output function (UART / RTT, etc.)
* This function must be implemented by the project.
* ------------------------------------------------- */
extern void board_print(const char *s);
/* -------------------------------------------------
* Global Lua state
* ------------------------------------------------- */
static lua_State *g_L = NULL;
/* -------------------------------------------------
* Initialize Lua VM
* ------------------------------------------------- */
void dr_lua_init(void)
{
g_L = luaL_newstate();
/* Load base library only */
luaL_requiref(g_L, "_G", luaopen_base, 1);
lua_pop(g_L, 1);
}
/* -------------------------------------------------
* Load Lua script
* Defines:
* function add3(x)
* return x + 3
* end
* ------------------------------------------------- */
void dr_lua_load_script(void)
{
const char *lua_code =
"function add3(x)\n"
" return x + 3\n"
"end";
if (luaL_dostring(g_L, lua_code) != LUA_OK) {
const char *err = lua_tostring(g_L, -1);
board_print(err);
lua_pop(g_L, 1);
}
}
/* -------------------------------------------------
* Core interface function
* Calls Lua function add3 from C firmware
*
* @param num1 Input integer value
* @return Result of (num1 + 3)
* -1 if Lua function is not found
* -2 if Lua call fails
* ------------------------------------------------- */
int dr_lua_add3(int num1)
{
int result = 0;
/* 1. Get Lua function: add3 */
lua_getglobal(g_L, "add3");
if (!lua_isfunction(g_L, -1)) {
lua_pop(g_L, 1);
return -1; /* Function not found */
}
/* 2. Push argument */
lua_pushinteger(g_L, num1);
/* 3. Call Lua function (1 argument, 1 return value) */
if (lua_pcall(g_L, 1, 1, 0) != LUA_OK) {
const char *err = lua_tostring(g_L, -1);
board_print(err);
lua_pop(g_L, 1);
return -2; /* Call failed */
}
/* 4. Read return value */
if (lua_isinteger(g_L, -1)) {
result = (int)lua_tointeger(g_L, -1);
}
/* 5. Clean up Lua stack */
lua_pop(g_L, 1);
return result; /* num1 + 3 */
}

View File

@@ -1,533 +0,0 @@
/*******************************************************************************
* @file dr_w25q32.c
* @brief W25Q32 SPI Flash Driver for nRF52840
* Software SPI (bit-bang) implementation
* @date 2026-03-12
*
* @details Bit-bang SPI driver for W25Q32 NOR Flash.
* SPI Mode 0 (CPOL=0, CPHA=0):
* - SCLK idle LOW
* - Data sampled on rising edge
* - Data shifted out on falling edge
*
* W25Q32 SPI timing:
* CS ──┐ ┌──
* └────────────────────────────────────┘
* CLK ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐
* ─────┘ └──┘ └──┘ └── ... ┘ └──┘ └────
* DI <CMD7><CMD6><CMD5>...<D1 ><D0 >
* DO <Z ><Z ><Z >...<D1 ><D0 >
******************************************************************************/
#include "dr_w25q32.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "debug_print.h"
#include <string.h>
/*==============================================================================
* PRIVATE DEFINES
*============================================================================*/
#define DR_PIN_NUM(pin) ((pin) & 0x1F)
#define DR_PIN_PORT(pin) (((pin) >> 5) & 0x01)
/* Pin masks for direct register access */
#define FLASH_CS_MASK (1UL << DR_PIN_NUM(DR_FLASH_PIN_CS))
#define FLASH_SCLK_MASK (1UL << DR_PIN_NUM(DR_FLASH_PIN_SCLK))
#define FLASH_MISO_MASK (1UL << DR_PIN_NUM(DR_FLASH_PIN_MISO))
#define FLASH_MOSI_MASK (1UL << DR_PIN_NUM(DR_FLASH_PIN_MOSI))
/* Port registers - all pins on P0 */
#define FLASH_PORT NRF_P0 // NRF_P0: 포트 레지스터에 접근하는 베이스 포인터(포트 전체 제어 X)
/* Timeout for busy wait (ms) */
#define BUSY_TIMEOUT_PAGE_PROGRAM 10
#define BUSY_TIMEOUT_SECTOR_ERASE 500
#define BUSY_TIMEOUT_BLOCK_ERASE 2000
#define BUSY_TIMEOUT_CHIP_ERASE 60000
/* W25Q32 JEDEC ID expected values */
#define W25Q32_MANUFACTURER_ID 0xEF
#define W25Q32_MEMORY_TYPE 0x40
#define W25Q32_CAPACITY 0x16
/*==============================================================================
* PRIVATE VARIABLES
*============================================================================*/
static bool m_initialized = false;
/*==============================================================================
* LOW-LEVEL SPI BIT-BANG
*
* W25Q32 uses SPI Mode 0:
* - CPOL=0: Clock idle LOW
* - CPHA=0: Data sampled on rising edge, shifted on falling edge
*============================================================================*/
static inline void flash_cs_low(void)
{
FLASH_PORT->OUTCLR = FLASH_CS_MASK;
}
static inline void flash_cs_high(void)
{
FLASH_PORT->OUTSET = FLASH_CS_MASK;
}
static inline void flash_sclk_low(void)
{
FLASH_PORT->OUTCLR = FLASH_SCLK_MASK;
}
static inline void flash_sclk_high(void)
{
FLASH_PORT->OUTSET = FLASH_SCLK_MASK;
}
static inline void flash_mosi_high(void)
{
FLASH_PORT->OUTSET = FLASH_MOSI_MASK;
}
static inline void flash_mosi_low(void)
{
FLASH_PORT->OUTCLR = FLASH_MOSI_MASK;
}
static inline uint32_t flash_read_miso(void)
{
return (FLASH_PORT->IN & FLASH_MISO_MASK) ? 1 : 0;
}
/**
* @brief Send one byte via SPI (MSB first)
*/
static void spi_send_byte(uint8_t byte)
{
for (int i = 7; i >= 0; i--)
{
/* Set MOSI */
if (byte & (1 << i))
flash_mosi_high();
else
flash_mosi_low();
/* Rising edge - data sampled by slave */
flash_sclk_high();
__NOP();
__NOP();
/* Falling edge */
flash_sclk_low();
__NOP();
}
}
/**
* @brief Receive one byte via SPI (MSB first)
* @note Sends 0xFF (MOSI high) while reading
*/
static uint8_t spi_recv_byte(void)
{
uint8_t byte = 0;
flash_mosi_high(); /* Keep MOSI high during read */
for (int i = 7; i >= 0; i--)
{
/* Rising edge - sample MISO */
flash_sclk_high();
__NOP();
__NOP();
if (flash_read_miso())
byte |= (1 << i);
/* Falling edge */
flash_sclk_low();
__NOP();
}
return byte;
}
/**
* @brief Initialize GPIO pins
*/
static void flash_gpio_init(void)
{
/* CS: Output, HIGH (deselected) */
nrf_gpio_cfg_output(DR_FLASH_PIN_CS);
nrf_gpio_pin_set(DR_FLASH_PIN_CS);
/* SCLK: Output, LOW (idle for Mode 0) */
nrf_gpio_cfg_output(DR_FLASH_PIN_SCLK);
nrf_gpio_pin_clear(DR_FLASH_PIN_SCLK);
/* MOSI: Output, HIGH */
nrf_gpio_cfg_output(DR_FLASH_PIN_MOSI);
nrf_gpio_pin_set(DR_FLASH_PIN_MOSI);
/* MISO: Input, no pull */
nrf_gpio_cfg_input(DR_FLASH_PIN_MISO, NRF_GPIO_PIN_NOPULL);
}
/**
* @brief Send Write Enable command (0x06)
*/
static void flash_write_enable(void)
{
flash_cs_low();
spi_send_byte(DR_FLASH_CMD_WRITE_ENABLE);
flash_cs_high();
__NOP(); __NOP(); __NOP(); __NOP();
}
/*==============================================================================
* PUBLIC FUNCTIONS - INITIALIZATION
*============================================================================*/
dr_flash_err_t dr_w25q32_init(void)
{
DBG_PRINTF("[FLASH] Init\n");
flash_gpio_init();
m_initialized = true;
DBG_PRINTF("[FLASH] Init OK\n");
return DR_FLASH_OK;
}
void dr_w25q32_uninit(void)
{
if (!m_initialized) return;
DBG_PRINTF("[FLASH] Uninit\n");
/* CS high (deselect) */
nrf_gpio_pin_set(DR_FLASH_PIN_CS);
/* Release pins to default */
nrf_gpio_cfg_default(DR_FLASH_PIN_CS);
/* Don't release shared pins (SCLK, MISO, MOSI) -
they may be in use by ADC121S051 */
m_initialized = false;
}
bool dr_w25q32_is_initialized(void)
{
return m_initialized;
}
/*==============================================================================
* PUBLIC FUNCTIONS - IDENTIFICATION
*============================================================================*/
dr_flash_err_t dr_w25q32_read_jedec_id(dr_flash_jedec_t *jedec) //JEDEC ID 읽기 (0xEF, 0x40, 0x16)
{
if (!m_initialized) return DR_FLASH_ERR_NOT_INIT;
if (!jedec) return DR_FLASH_ERR_INVALID_PARAM;
flash_cs_low();
spi_send_byte(DR_FLASH_CMD_READ_JEDEC_ID);
jedec->manufacturer_id = spi_recv_byte();
jedec->memory_type = spi_recv_byte();
jedec->capacity = spi_recv_byte();
flash_cs_high();
DBG_PRINTF("[FLASH] JEDEC ID: 0x%02X 0x%02X 0x%02X\n",
jedec->manufacturer_id, jedec->memory_type, jedec->capacity);
return DR_FLASH_OK;
}
dr_flash_err_t dr_w25q32_read_uid(uint8_t *uid) // 8바이트 고유 ID 읽기
{
if (!m_initialized) return DR_FLASH_ERR_NOT_INIT;
if (!uid) return DR_FLASH_ERR_INVALID_PARAM;
flash_cs_low();
spi_send_byte(DR_FLASH_CMD_READ_UID);
/* 4 dummy bytes */
spi_send_byte(0x00);
spi_send_byte(0x00);
spi_send_byte(0x00);
spi_send_byte(0x00);
/* 8-byte unique ID */
for (int i = 0; i < DR_FLASH_UID_LENGTH; i++)
{
uid[i] = spi_recv_byte();
}
flash_cs_high();
DBG_PRINTF("[FLASH] UID: %02X%02X%02X%02X%02X%02X%02X%02X\n",
uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]);
return DR_FLASH_OK;
}
/*==============================================================================
* PUBLIC FUNCTIONS - STATUS
*============================================================================*/
dr_flash_err_t dr_w25q32_read_status(uint8_t *status)
{
if (!m_initialized) return DR_FLASH_ERR_NOT_INIT;
if (!status) return DR_FLASH_ERR_INVALID_PARAM;
flash_cs_low();
spi_send_byte(DR_FLASH_CMD_READ_STATUS1);
*status = spi_recv_byte();
flash_cs_high();
return DR_FLASH_OK;
}
bool dr_w25q32_is_busy(void)
{
uint8_t status = 0;
dr_w25q32_read_status(&status);
return (status & DR_FLASH_SR1_BUSY) ? true : false;
}
dr_flash_err_t dr_w25q32_wait_busy(uint32_t timeout_ms)
{
if (!m_initialized) return DR_FLASH_ERR_NOT_INIT;
while (timeout_ms > 0)
{
if (!dr_w25q32_is_busy())
return DR_FLASH_OK;
nrf_delay_ms(1);
timeout_ms--;
}
return DR_FLASH_ERR_TIMEOUT;
}
/*==============================================================================
* PUBLIC FUNCTIONS - READ
*============================================================================*/
dr_flash_err_t dr_w25q32_read(uint32_t addr, uint8_t *buf, uint32_t len) // 데이터 읽기 (주소, 길이)
{
if (!m_initialized) return DR_FLASH_ERR_NOT_INIT;
if (!buf || len == 0) return DR_FLASH_ERR_INVALID_PARAM;
if (addr + len > DR_FLASH_TOTAL_SIZE) return DR_FLASH_ERR_INVALID_PARAM;
DBG_PRINTF("[FLASH] Read addr=0x%06X len=%d\n", addr, len);
flash_cs_low();
/* Command + 24-bit address */
spi_send_byte(DR_FLASH_CMD_READ_DATA);
spi_send_byte((addr >> 16) & 0xFF);
spi_send_byte((addr >> 8) & 0xFF);
spi_send_byte((addr ) & 0xFF);
/* Read data */
for (uint32_t i = 0; i < len; i++)
{
buf[i] = spi_recv_byte();
}
flash_cs_high();
return DR_FLASH_OK;
}
/*==============================================================================
* PUBLIC FUNCTIONS - WRITE
*============================================================================*/
dr_flash_err_t dr_w25q32_write(uint32_t addr, const uint8_t *data, uint32_t len) // 페이지 쓰기 (최대 256B)
{
if (!m_initialized) return DR_FLASH_ERR_NOT_INIT;
if (!data || len == 0 || len > DR_FLASH_PAGE_SIZE)
return DR_FLASH_ERR_INVALID_PARAM;
if (addr + len > DR_FLASH_TOTAL_SIZE)
return DR_FLASH_ERR_INVALID_PARAM;
/* Check page boundary crossing */
uint32_t page_offset = addr % DR_FLASH_PAGE_SIZE;
if (page_offset + len > DR_FLASH_PAGE_SIZE)
return DR_FLASH_ERR_INVALID_PARAM;
DBG_PRINTF("[FLASH] Write addr=0x%06X len=%d\n", addr, len);
/* Write Enable */
flash_write_enable();
/* Page Program */
flash_cs_low();
spi_send_byte(DR_FLASH_CMD_PAGE_PROGRAM);
spi_send_byte((addr >> 16) & 0xFF);
spi_send_byte((addr >> 8) & 0xFF);
spi_send_byte((addr ) & 0xFF);
for (uint32_t i = 0; i < len; i++)
{
spi_send_byte(data[i]);
}
flash_cs_high();
/* Wait for programming to complete */
dr_flash_err_t err = dr_w25q32_wait_busy(BUSY_TIMEOUT_PAGE_PROGRAM);
if (err != DR_FLASH_OK)
DBG_PRINTF("[FLASH] Write TIMEOUT!\n");
return err;
}
/*==============================================================================
* PUBLIC FUNCTIONS - ERASE
*============================================================================*/
dr_flash_err_t dr_w25q32_erase_sector(uint32_t addr) // 4KB 섹터 삭제
{
if (!m_initialized) return DR_FLASH_ERR_NOT_INIT;
if (addr >= DR_FLASH_TOTAL_SIZE) return DR_FLASH_ERR_INVALID_PARAM;
DBG_PRINTF("[FLASH] Erase sector addr=0x%06X\n", addr);
flash_write_enable();
flash_cs_low();
spi_send_byte(DR_FLASH_CMD_SECTOR_ERASE);
spi_send_byte((addr >> 16) & 0xFF);
spi_send_byte((addr >> 8) & 0xFF);
spi_send_byte((addr ) & 0xFF);
flash_cs_high();
dr_flash_err_t err = dr_w25q32_wait_busy(BUSY_TIMEOUT_SECTOR_ERASE);
if (err != DR_FLASH_OK)
DBG_PRINTF("[FLASH] Erase sector TIMEOUT!\n");
return err;
}
dr_flash_err_t dr_w25q32_erase_block_32k(uint32_t addr) // 블록 삭제
{
if (!m_initialized) return DR_FLASH_ERR_NOT_INIT;
if (addr >= DR_FLASH_TOTAL_SIZE) return DR_FLASH_ERR_INVALID_PARAM;
DBG_PRINTF("[FLASH] Erase block 32K addr=0x%06X\n", addr);
flash_write_enable();
flash_cs_low();
spi_send_byte(DR_FLASH_CMD_BLOCK_ERASE_32K);
spi_send_byte((addr >> 16) & 0xFF);
spi_send_byte((addr >> 8) & 0xFF);
spi_send_byte((addr ) & 0xFF);
flash_cs_high();
dr_flash_err_t err = dr_w25q32_wait_busy(BUSY_TIMEOUT_BLOCK_ERASE);
if (err != DR_FLASH_OK)
DBG_PRINTF("[FLASH] Erase block 32K TIMEOUT!\n");
return err;
}
dr_flash_err_t dr_w25q32_erase_block_64k(uint32_t addr) // 블록 삭제
{
if (!m_initialized) return DR_FLASH_ERR_NOT_INIT;
if (addr >= DR_FLASH_TOTAL_SIZE) return DR_FLASH_ERR_INVALID_PARAM;
DBG_PRINTF("[FLASH] Erase block 64K addr=0x%06X\n", addr);
flash_write_enable();
flash_cs_low();
spi_send_byte(DR_FLASH_CMD_BLOCK_ERASE_64K);
spi_send_byte((addr >> 16) & 0xFF);
spi_send_byte((addr >> 8) & 0xFF);
spi_send_byte((addr ) & 0xFF);
flash_cs_high();
dr_flash_err_t err = dr_w25q32_wait_busy(BUSY_TIMEOUT_BLOCK_ERASE);
if (err != DR_FLASH_OK)
DBG_PRINTF("[FLASH] Erase block 64K TIMEOUT!\n");
return err;
}
dr_flash_err_t dr_w25q32_chip_erase(void) // 전체 삭제
{
if (!m_initialized) return DR_FLASH_ERR_NOT_INIT;
DBG_PRINTF("[FLASH] Chip erase...\n");
flash_write_enable();
flash_cs_low();
spi_send_byte(DR_FLASH_CMD_CHIP_ERASE);
flash_cs_high();
dr_flash_err_t err = dr_w25q32_wait_busy(BUSY_TIMEOUT_CHIP_ERASE);
if (err == DR_FLASH_OK)
DBG_PRINTF("[FLASH] Chip erase OK\n");
else
DBG_PRINTF("[FLASH] Chip erase TIMEOUT!\n");
return err;
}
/*==============================================================================
* PUBLIC FUNCTIONS - POWER MANAGEMENT
*============================================================================*/
dr_flash_err_t dr_w25q32_deep_powerdown(void) // 저전력 모드 (~1uA)
{
if (!m_initialized) return DR_FLASH_ERR_NOT_INIT;
DBG_PRINTF("[FLASH] Deep power-down\n");
flash_cs_low();
spi_send_byte(DR_FLASH_CMD_POWER_DOWN);
flash_cs_high();
/* tDP: CS high to deep power-down = 3us max */
nrf_delay_us(5);
return DR_FLASH_OK;
}
dr_flash_err_t dr_w25q32_wakeup(void) // 저전력 모드 해제(깨우기)
{
if (!m_initialized) return DR_FLASH_ERR_NOT_INIT;
DBG_PRINTF("[FLASH] Wakeup\n");
flash_cs_low();
spi_send_byte(DR_FLASH_CMD_RELEASE_PD);
flash_cs_high();
/* tRES1: CS high to standby = 3us max */
nrf_delay_us(5);
return DR_FLASH_OK;
}
/*==============================================================================
* PUBLIC FUNCTIONS - DEBUG / TEST
*============================================================================*/
bool dr_w25q32_test(void) // JEDEC ID로 통신 테스트
{
dr_flash_jedec_t jedec;
if (dr_w25q32_read_jedec_id(&jedec) != DR_FLASH_OK)
{
DBG_PRINTF("[FLASH] Test FAIL - read error\n");
return false;
}
bool pass = (jedec.manufacturer_id == W25Q32_MANUFACTURER_ID &&
jedec.memory_type == W25Q32_MEMORY_TYPE &&
jedec.capacity == W25Q32_CAPACITY);
DBG_PRINTF("[FLASH] Test %s\n", pass ? "PASS" : "FAIL");
return pass;
}

View File

@@ -1,245 +0,0 @@
/*******************************************************************************
* @file dr_w25q32.h
* @brief W25Q32 SPI Flash Driver for nRF52840
* 32Mbit (4MB) Serial NOR Flash Memory
* @date 2026-03-12
*
* @details Software SPI (bit-bang) driver for W25Q32RVXHJQ.
* Shares SPI bus (SCK/MISO/MOSI) with ADC121S051.
* Only CS pin is unique (P0.24).
*
* Pin connections:
* nRF52840 W25Q32 (U16)
* P0.24 -----> /CS (pin 1)
* P0.15 <----- DO (pin 2, MISO)
* P0.16 -----> DI (pin 5, MOSI)
* P0.14 -----> CLK (pin 6)
*
* @note WP (pin 3) and HOLD (pin 7) are pulled HIGH via 10k resistors.
******************************************************************************/
#ifndef DR_W25Q32_H
#define DR_W25Q32_H
#include <stdint.h>
#include <stdbool.h>
#include "nrf_gpio.h"
/*==============================================================================
* PIN CONFIGURATION
*============================================================================*/
#define DR_FLASH_PIN_CS NRF_GPIO_PIN_MAP(0, 24) /* Chip Select - SPI_CS_FLASH(P0.24) */
#define DR_FLASH_PIN_SCLK NRF_GPIO_PIN_MAP(0, 14) /* Serial Clock(shared) - SPI_SCK(P0.14) */
#define DR_FLASH_PIN_MISO NRF_GPIO_PIN_MAP(0, 15) /* DI_(IO0)(shared) - SPI_MOSI(P0.15) */
#define DR_FLASH_PIN_MOSI NRF_GPIO_PIN_MAP(0, 16) /* DO_(IO1)(shared) - SPI_MISO(P0.16) */
/*==============================================================================
* W25Q32 SPECIFICATIONS
*============================================================================*/
#define DR_FLASH_PAGE_SIZE 256 /**< Page size (bytes) */
#define DR_FLASH_SECTOR_SIZE 4096 /**< Sector size (bytes, 4KB) */
#define DR_FLASH_BLOCK_32K (32*1024) /**< 32KB block */
#define DR_FLASH_BLOCK_64K (64*1024) /**< 64KB block */
#define DR_FLASH_TOTAL_SIZE (4*1024*1024) /**< 4MB total */
#define DR_FLASH_UID_LENGTH 8 /**< Unique ID length (bytes) */
/*==============================================================================
* W25Q32 COMMAND OPCODES
*============================================================================*/
#define DR_FLASH_CMD_WRITE_ENABLE 0x06
#define DR_FLASH_CMD_WRITE_DISABLE 0x04
#define DR_FLASH_CMD_READ_STATUS1 0x05
#define DR_FLASH_CMD_READ_STATUS2 0x35
#define DR_FLASH_CMD_WRITE_STATUS 0x01
#define DR_FLASH_CMD_READ_DATA 0x03
#define DR_FLASH_CMD_PAGE_PROGRAM 0x02
#define DR_FLASH_CMD_SECTOR_ERASE 0x20 /**< 4KB erase */
#define DR_FLASH_CMD_BLOCK_ERASE_32K 0x52 /**< 32KB erase */
#define DR_FLASH_CMD_BLOCK_ERASE_64K 0xD8 /**< 64KB erase */
#define DR_FLASH_CMD_CHIP_ERASE 0xC7 /**< Full chip erase */
#define DR_FLASH_CMD_POWER_DOWN 0xB9 /**< Deep power-down */
#define DR_FLASH_CMD_RELEASE_PD 0xAB /**< Release from deep power-down */
#define DR_FLASH_CMD_READ_UID 0x4B /**< Read unique ID */
#define DR_FLASH_CMD_READ_JEDEC_ID 0x9F /**< Read JEDEC ID */
#define DR_FLASH_CMD_READ_MFR_ID 0x90 /**< Read manufacturer/device ID */
/* Status Register 1 bits */
#define DR_FLASH_SR1_BUSY 0x01 /**< Erase/Write in progress */
#define DR_FLASH_SR1_WEL 0x02 /**< Write enable latch */
/*==============================================================================
* ERROR CODES
*============================================================================*/
typedef enum {
DR_FLASH_OK = 0,
DR_FLASH_ERR_NOT_INIT,
DR_FLASH_ERR_INVALID_PARAM,
DR_FLASH_ERR_TIMEOUT,
DR_FLASH_ERR_WRITE_FAILED,
DR_FLASH_ERR_JEDEC_MISMATCH
} dr_flash_err_t;
/*==============================================================================
* DATA STRUCTURES
*============================================================================*/
/** @brief JEDEC ID structure */
typedef struct {
uint8_t manufacturer_id; /**< 0xEF = Winbond */
uint8_t memory_type; /**< 0x40 = SPI */
uint8_t capacity; /**< 0x16 = 32Mbit */
} dr_flash_jedec_t;
/*==============================================================================
* INITIALIZATION
*============================================================================*/
/**
* @brief Initialize W25Q32 Flash driver
* @return dr_flash_err_t Error code
* @note Sets up GPIO pins. Does NOT wake chip from deep power-down.
*/
dr_flash_err_t dr_w25q32_init(void);
/**
* @brief Uninitialize driver, release GPIO pins
*/
void dr_w25q32_uninit(void);
/**
* @brief Check if driver is initialized
*/
bool dr_w25q32_is_initialized(void);
/*==============================================================================
* IDENTIFICATION
*============================================================================*/
/**
* @brief Read JEDEC ID (manufacturer, type, capacity)
* @param jedec Pointer to JEDEC ID structure
* @return dr_flash_err_t Error code
* @note Expected: manufacturer=0xEF, type=0x40, capacity=0x16
*/
dr_flash_err_t dr_w25q32_read_jedec_id(dr_flash_jedec_t *jedec);
/**
* @brief Read 8-byte unique ID
* @param uid Buffer to store 8-byte UID (must be >= 8 bytes)
* @return dr_flash_err_t Error code
*/
dr_flash_err_t dr_w25q32_read_uid(uint8_t *uid);
/*==============================================================================
* READ
*============================================================================*/
/**
* @brief Read data from flash
* @param addr 24-bit start address (0x000000 ~ 0x3FFFFF)
* @param buf Buffer to store read data
* @param len Number of bytes to read
* @return dr_flash_err_t Error code
*/
dr_flash_err_t dr_w25q32_read(uint32_t addr, uint8_t *buf, uint32_t len);
/*==============================================================================
* WRITE
*============================================================================*/
/**
* @brief Write data to flash (page program, max 256 bytes)
* @param addr 24-bit start address (must be page-aligned for best results)
* @param data Data to write
* @param len Number of bytes (1~256, must not cross page boundary)
* @return dr_flash_err_t Error code
* @note Automatically sends Write Enable before programming.
* Waits for completion (BUSY flag).
*/
dr_flash_err_t dr_w25q32_write(uint32_t addr, const uint8_t *data, uint32_t len);
/*==============================================================================
* ERASE
*============================================================================*/
/**
* @brief Erase 4KB sector
* @param addr Any address within the sector to erase
* @return dr_flash_err_t Error code
* @note Typical 45ms, max 400ms. Waits for completion.
*/
dr_flash_err_t dr_w25q32_erase_sector(uint32_t addr);
/**
* @brief Erase 32KB block
* @param addr Any address within the block
* @return dr_flash_err_t Error code
*/
dr_flash_err_t dr_w25q32_erase_block_32k(uint32_t addr);
/**
* @brief Erase 64KB block
* @param addr Any address within the block
* @return dr_flash_err_t Error code
*/
dr_flash_err_t dr_w25q32_erase_block_64k(uint32_t addr);
/**
* @brief Erase entire chip
* @return dr_flash_err_t Error code
* @note Takes 6~50 seconds. Use with caution.
*/
dr_flash_err_t dr_w25q32_chip_erase(void);
/*==============================================================================
* POWER MANAGEMENT
*============================================================================*/
/**
* @brief Enter deep power-down mode (~1uA)
* @return dr_flash_err_t Error code
*/
dr_flash_err_t dr_w25q32_deep_powerdown(void);
/**
* @brief Release from deep power-down
* @return dr_flash_err_t Error code
* @note Requires ~3us recovery time (handled internally)
*/
dr_flash_err_t dr_w25q32_wakeup(void);
/*==============================================================================
* STATUS
*============================================================================*/
/**
* @brief Read Status Register 1
* @param status Pointer to store status byte
* @return dr_flash_err_t Error code
*/
dr_flash_err_t dr_w25q32_read_status(uint8_t *status);
/**
* @brief Check if flash is busy (erase/write in progress)
* @return true if busy
*/
bool dr_w25q32_is_busy(void);
/**
* @brief Wait until flash is not busy
* @param timeout_ms Maximum wait time in milliseconds
* @return dr_flash_err_t DR_FLASH_OK or DR_FLASH_ERR_TIMEOUT
*/
dr_flash_err_t dr_w25q32_wait_busy(uint32_t timeout_ms);
/*==============================================================================
* DEBUG / TEST
*============================================================================*/
/**
* @brief Test flash communication by reading JEDEC ID
* @return true if JEDEC ID matches W25Q32 (0xEF, 0x40, 0x16)
*/
bool dr_w25q32_test(void);
#endif /* DR_W25Q32_H */

View File

@@ -1,2 +0,0 @@
gcc -std=c99 -Wall -Wextra -o parser.exe parser.c pcmain.c

View File

@@ -1,59 +0,0 @@
/* pcmain.c : PC에서 parser 테스트용 main
* - 펌웨어에서는 이 파일 사용하지 않음
*/
#include <stdio.h>
#include <stdarg.h>
#include "parser.h"
/* PC용 로그 함수 */
static void pc_log(const char *fmt, ...)
{
if (!g_log_enable) {
return;
}
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
}
/* PC용 바이너리 전송 함수 */
static void pc_tx_bin(const uint8_t *buf, uint16_t len)
{
uint16_t i;
printf("[TX] ");
for (i = 0; i < len; i++) {
printf("%02X ", buf[i]);
}
printf("\n");
}
int main(void)
{
/* 플랫폼 함수 설정 */
g_plat.log = pc_log;
g_plat.tx_bin = pc_tx_bin;
g_log_enable = true; /* 필요시 false로 전체 로그 끄기 */
/* 테스트 1: sta? (mode=1) */
{
uint8_t buf[6] = { 's','s','n','?' }; /* value0=1 */
dr_cmd_parser(buf, 4);
}
/* 테스트 2: ssz? (Serial 12바이트) */
{
const char *serial = "ABC123456789";
uint8_t buf[4 + 12];
uint8_t i;
buf[0] = 's'; buf[1] = 's'; buf[2] = 'z'; buf[3] = '?';
for (i = 0; i < 12; i++) {
buf[4 + i] = (uint8_t)serial[i];
}
dr_cmd_parser(buf, 4 + 12);
}
return 0;
}