Skip to content
Open
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 ([email protected])
* @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 ([email protected])
* @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 ([email protected])
* @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