Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions middleware/include/eeprom_alloc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* @file eeprom_alloc.h
* @author Sogo Nishihara (sogonishi@gmail.com)
* @brief EEPROM Block Allocation Management
* @version 0.1
* @date 2026-01-02
*
* This file provides functions for managing data block allocation in the
* EEPROM. It maintains a bit-vector allocation table to track which blocks are
* in use.
*
*/

#ifndef EEPROM_ALLOC_H
#define EEPROM_ALLOC_H

#include <stdio.h>

#include "eeprom_directory_struct.h"

/**
* @brief Initialize allocation table by loading it from EEPROM memory.
*
* This function reads the allocation table from EEPROM and populates the
* directory's alloc_table structure in memory.
*
* @param directory Pointer to the initialized directory structure.
*
* @return eeprom_status_t Returns EEPROM_OK on success, or an error code on
* failure.
*
* @retval EEPROM_ERROR If EEPROM read operation fails.
*/
eeprom_status_t init_alloc_table(eeprom_directory_t *directory);

/**
* @brief Print the allocation table in a human-readable format.
*
* This function prints the allocation table showing which blocks are allocated
* (1) and which are free (0). The output is formatted with 8 bits per group and
* 64 bits per line.
*
* @param directory Pointer to the initialized directory structure.
*/
void print_alloc_table(eeprom_directory_t *directory);

/**
* @brief Allocate a single block from the EEPROM.
*
* This function finds the first free block in the allocation table, marks it as
* allocated in both local memory and EEPROM, and returns its ID.
*
* @param directory Pointer to the initialized directory structure.
*
* @return uint16_t Returns the allocated block ID on success, or BLOCK_COUNT if
* allocation fails.
*
* @retval BLOCK_COUNT If no free blocks are available or EEPROM update fails.
*/
uint16_t alloc_block(eeprom_directory_t *directory);

/**
* @brief Free one or more blocks in the EEPROM.
*
* This function marks the specified blocks as free in both local memory and
* EEPROM. If a block is already freed, this function does nothing for that
* block.
*
* @param directory Pointer to the initialized directory structure.
* @param ids Array of block IDs to free.
* @param size Number of block IDs in the array.
*/
void free_block(eeprom_directory_t *directory, uint16_t *ids, uint8_t size);

/**
* @brief Check if a block is allocated.
*
* This function checks the allocation table to determine if a specific block is
* currently allocated or free.
*
* @param directory Pointer to the initialized directory structure.
* @param id Block ID to check.
*
* @return int Returns 1 if the block is allocated, 0 if it is free.
*/
int is_allocated(eeprom_directory_t *directory, uint16_t id);

#endif
158 changes: 95 additions & 63 deletions middleware/include/eeprom_directory.h
Original file line number Diff line number Diff line change
@@ -1,83 +1,115 @@
/**
* @file eepromdirectory.h
* @brief EEPROM Directory Management
*
* This file provides functions to initialize and manage an EEPROM directory with partitions.
* Functions return `eeprom_status_t` error codes, which are defined in `eeprom_status.h`.
*
*/
* @file eeprom_directory.h
* @author Sogo Nishihara (sogonishi@gmail.com)
* @brief EEPROM Directory Management API
*
* This file defines the public API for a simple key-value directory
* stored on EEPROM device.
*
* The directory provides block-based persistent storage, managing
* allocation, lookup, insertion, and deletion of values associated
* with fixed-size (4-byte) keys.
*
* All functions return eeprom_status_t error codes defined in
* eeprom_status.h. */

#ifndef EEPROM_DIRECTORY_H
#define EEPROM_DIRECTORY_H

#include "eeprom_status.h"
#include <stddef.h>
#include <stdint.h>

struct partition_cfg {
const char *id; /* The ID of the partition */
uint16_t size; /* The size of the partition in bytes */
uint16_t address;
uint16_t head_address;
};
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
struct partition_cfg *partitions;
size_t num_partitions;
} eeprom_directory_t;
#include "eeprom_alloc.h"
#include "eeprom_directory_struct.h"
#include "eeprom_status.h"
#include "eeprom_storage.h"
#include "m24c32.h"

/**
* @brief Initializes an EEPROM directory with partition IDs and sizes.
*
* This function sets up partition configurations within the EEPROM memory.
* The total allocated address space is calculated based on the provided partitions.
*
* @param directory Pointer to the EEPROM directory structure.
* @param partitions Array of partition configurations, including IDs and sizes.
* @param num_partitions Number of partitions to create.
* @return eeprom_status_t Returns EEPROM_OK on success or an error code on failure.
* @brief Initialize the EEPROM directory structure.
*
* This function initializes the directory structure with the provided device
* interface, loads the allocation table and key map from EEPROM memory.
*
* @param device Pointer to the M24C32 device interface structure.
* @param directory Pointer to the directory structure to initialize. Must be
* allocated by caller.
*
* @return eeprom_status_t Returns EEPROM_OK on success, or an error code on
* failure.
*
* @retval EEPROM_ERROR_NULL_POINTER If device or directory is NULL.
* @retval EEPROM_ERROR If initialization of alloc table or storage fails.
*/
eeprom_status_t directory_init(eeprom_directory_t *directory,
const struct partition_cfg partitions[],
size_t num_partitions);
eeprom_status_t directory_init(m24c32_t *device, eeprom_directory_t *directory);

/**
* @brief Get the address of the beginning of a partition.
*
* This function searches for a partition by its name and returns its starting address.
*
* @param directory Pointer to the EEPROM directory structure.
* @param key Name of the partition.
* @param address Pointer to store the retrieved base address.
* @return eeprom_status_t Returns EEPROM_OK on success or an error code if the partition is not found.
* @brief Retrieve a value from the directory by key.
*
* This function looks up a key in the directory and retrieves the associated
* data. The output buffer is allocated by this function and must be freed by
* the caller.
*
* @param directory Pointer to the initialized directory structure.
* @param key Pointer to a 4-byte key (not null-terminated).
* @param out Pointer to a pointer that will receive the allocated output
* buffer. The caller is responsible for freeing this buffer.
* @param out_size Pointer to store the size of the output data in bytes.
*
* @return eeprom_status_t Returns EEPROM_OK on success, or an error code on
* failure.
*
* @retval EEPROM_ERROR_NULL_POINTER If directory, key, out, or out_size is
* NULL.
* @retval EEPROM_ERROR_NOT_FOUND If the key does not exist in the directory.
* @retval EEPROM_ERROR_ALLOCATION If memory allocation fails.
*/
eeprom_status_t eeprom_get_base_address(const eeprom_directory_t *directory,
const char *key, uint16_t *address);
eeprom_status_t get_directory_value(eeprom_directory_t *directory,
const uint8_t *key, uint8_t **out,
uint16_t *out_size);

/**
* @brief Get the current read/write head of a partition.
*
* This function provides the address of the next location available for writing within the partition.
*
* @param directory Pointer to EEPROM directory struct.
* @param key Name of the partition.
* @param address Pointer to store the retrieved head address.
* @return eeprom_status_t Returns EEPROM_OK on success or an error code if the partition is not found.
* @brief Store a value in the directory with the specified key.
*
* This function stores data in the directory. If the key already exists, the
* old value is deleted first. The data is stored in blocks of BLOCK_SIZE bytes,
* with remaining bytes padded with zeros.
*
* @param directory Pointer to the initialized directory structure.
* @param key Pointer to a 4-byte key (not null-terminated).
* @param value Pointer to the data to store.
* @param value_size Size of the data in bytes (maximum 16 bytes, i.e., 4
* blocks).
*
* @return eeprom_status_t Returns EEPROM_OK on success, or an error code on
* failure.
*
* @retval EEPROM_ERROR_NULL_POINTER If directory or value is NULL.
* @retval EEPROM_ERROR If value_size is 0.
* @retval EEPROM_ERROR_TOO_BIG If value_size exceeds 16 bytes (4 blocks).
* @retval EEPROM_ERROR_ALLOCATION If block allocation fails.
*/
eeprom_status_t eeprom_get_head_address(const eeprom_directory_t *directory,
const char *key, uint16_t *address);
eeprom_status_t set_directory_value(eeprom_directory_t *directory,
const uint8_t *key, uint8_t *value,
const uint16_t value_size);

/**
* @brief Get the size of a partition
*
* This function returns the allocated size of a specific partition in bytes.
*
* @param directory Pointer to EEPROM directory struct.
* @param key Name of a partition.
* @param size Pointer to store the partition size.
* @return eeprom_status_t Returns EEPROM_OK on success or an error code if the partition is not found.
* @brief Delete a value from the directory by key.
*
* This function removes a key-value pair from the directory and frees the
* associated blocks. The blocks are marked as available for reuse.
*
* @param directory Pointer to the initialized directory structure.
* @param key Pointer to a 4-byte key (not null-terminated).
*
* @return eeprom_status_t Returns EEPROM_OK on success, or an error code on
* failure.
*
* @retval EEPROM_ERROR_NULL_POINTER If directory or key is NULL.
* @retval EEPROM_ERROR_NOT_FOUND If the key does not exist in the directory.
*/
eeprom_status_t eeprom_get_size(const eeprom_directory_t *directory,
const char *key, uint16_t *size);
eeprom_status_t delete_directory_value(eeprom_directory_t *directory,
const uint8_t *key);

#endif // EEPROM_DIRECTORY_H
110 changes: 110 additions & 0 deletions middleware/include/eeprom_directory_struct.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/**
* @file eeprom_directory_struct.h
* @author Sogo Nishihara (sogonishi@gmail.com)
* @brief EEPROM Directory Data Structures and Constants
* @version 0.1
* @date 2026-01-02
*
* This file defines the data structures and constants used for the EEPROM
* directory system. It includes memory layout definitions, block allocation
* parameters, and structure definitions.
*
* EEPROM Memory Layout (Total: 4096 bytes)
*
* Address
* 0x0000
* +--------------------------------------------------+
* | Allocation Table |
* | - Bit map (1 bit per data block) |
* | - Size : ALLOC_TABLE_SIZE bytes |
* | - Blocks : BLOCK_COUNT |
* +--------------------------------------------------+
* | Key Map Table |
* | - Array of directory_key_map_t |
* | - Entry size : KEY_MAP_STRUCT_SIZE bytes |
* | - Entry count: KEY_MAP_COUNT |
* | - Total size : KEY_MAP_SIZE bytes |
* +--------------------------------------------------+
* | Data Space |
* | - Data blocks |
* | - Block size : BLOCK_SIZE bytes |
* | - Block count: BLOCK_COUNT |
* | |
* | +------------------+ |
* | | Block 0 | |
* | +------------------+ |
* | | Block 1 | |
* | +------------------+ |
* | | ... | |
* | +------------------+ |
* | | Block N | |
* | +------------------+ |
* +--------------------------------------------------+
* 0x0FFF
*/

#ifndef EEPROM_DIRECTORY_STRUCT
#define EEPROM_DIRECTORY_STRUCT

/** @brief Size of a single key-map entry structure in bytes (4-byte key +
* 8-byte IDs array). */
#define KEY_MAP_STRUCT_SIZE 12

/** @brief Maximum number of key-value pairs that can be stored in the
* directory. */
#define KEY_MAP_COUNT 128

/** @brief Size of a data block in bytes. */
#define BLOCK_SIZE 4

/** @brief Total number of data blocks available in the EEPROM. */
#define BLOCK_COUNT 512

/** @brief Starting address of the allocation table in EEPROM. */
#define ALLOC_TABLE_BEGIN 0

/** @brief Size of the allocation table in bytes (one bit per block). */
#define ALLOC_TABLE_SIZE (BLOCK_COUNT / 8)

/** @brief Starting address of the key-map table in EEPROM. */
#define KEY_MAP_BEGIN (ALLOC_TABLE_BEGIN + ALLOC_TABLE_SIZE)

/** @brief Total size of the key-map table in bytes. */
#define KEY_MAP_SIZE (KEY_MAP_STRUCT_SIZE * KEY_MAP_COUNT)

/** @brief Starting address of the data space in EEPROM. */
#define DATA_SPACE_BEGIN (KEY_MAP_BEGIN + KEY_MAP_SIZE)

/** @brief Total size of the EEPROM in bytes. */
#define EEPROM_SIZE 4096

#include <stdint.h>

#include "m24c32.h"

/**
* @brief Key-value mapping structure.
*
* This structure maps a 4-byte key to up to 4 block IDs. Each block ID points
* to a BLOCK_SIZE-byte data block in the EEPROM data space.
*/
typedef struct {
uint8_t key[4]; /** 4-byte key (not null-terminated). */
uint16_t ids[4]; /** Array of up to 4 block IDs (BLOCK_COUNT indicates end). */
} directory_key_map_t;

/**
* @brief Main EEPROM directory structure.
*
* This structure contains all the state information for the EEPROM directory,
* including the device interface, allocation table, and key map.
*/
typedef struct {
m24c32_t *device; /** Pointer to the M24C32 device interface. */
uint8_t alloc_table[ALLOC_TABLE_SIZE]; /** Bit-vector allocation table (one
bit per block). */
directory_key_map_t
key_map[KEY_MAP_COUNT]; /** Array of key-value mappings. */
} eeprom_directory_t;

#endif
Loading