fix: BLE TX 먹통 해결 및 메모리 안전성 개선
- binary_tx_handler를 dr_binary_tx_safe로 전체 교체 (APP_ERROR_CHECK 제거) - data_tx_handler APP_ERROR_CHECK → DBG_PRINTF 교체 - memset/memcpy 하드코딩 크기를 define 상수로 교체 (버퍼 오버런 수정) - SERIAL_NO_LENGTH, HW_NO_LENGTH, PASSKEY_LENGTH를 main.h로 통합 - 미사용 HW 드라이버/EEPROM 코드 삭제, TWI를 i2c_manager.c로 통합 - EEPROM → FDS 전환, 코드 리뷰 현황 문서 추가 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
245
pc_firm/dr_w25q32/dr_w25q32.h
Normal file
245
pc_firm/dr_w25q32/dr_w25q32.h
Normal file
@@ -0,0 +1,245 @@
|
||||
/*******************************************************************************
|
||||
* @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 */
|
||||
Reference in New Issue
Block a user