Arduino Core for Renesas

repository·main·Indexed 41 days ago

https://github.com/arduino/arduinocore-renesas

Arduino Core support for Renesas FSP (Flexible Software Package) based boards, enabling Arduino programming models on Renesas RA microcontrollers. Includes documentation for compiling and loading bootloaders for PORTENTA_C33, UNO R4 WiFi, and UNO R4 Minima, as well as guides for implementing littlefs, building lwIP, and configuring mbedTLS libraries.

Tokens
28.2K
Snippets
79
Records
125
Agent score
52%

What's inside Arduino Renesas Core

  1. Overview of WiFiS3 classes

    main

    The WiFiS3 library provides several classes for managing different types of Wi-Fi communication:

    • WiFiClient: Represents a Wi-Fi client that connects to a remote server over a Wi-Fi network.
    • WiFiFileSystem: Handles WiFi file system operations.
    • WiFiServer: Provides server functionality for WiFi-based communication.
    • WiFiSSLClient: A specialized client class for secure SSL/TLS connections.
    • WiFiUDP: Handles UDP communication over a Wi-Fi network.
  2. What is littlefs and why use it?

    main

    littlefs is a fail-safe filesystem specifically designed for microcontrollers. It addresses the unique constraints of embedded systems, such as limited RAM/ROM and the physical characteristics of flash memory (where erasing is expensive and programming is granular).

    Use littlefs when your project requires:

    1. Power-loss resilience: The filesystem is designed to recover from power loss during any write operation, preventing data corruption that could render a device unrecoverable.
    2. Wear leveling: It prevents premature hardware failure by distributing writes across the flash storage, avoiding the exhaustion of specific blocks used for frequently updated metadata.
    3. Bounded RAM/ROM usage: Unlike many filesystems that require large amounts of memory to manage metadata, littlefs uses a bounded amount of RAM. This means RAM usage does not grow as the filesystem size or the number of files increases.
  3. How littlefs ensures data integrity with CRC tags

    main

    The LFS_TYPE_CRC (0x5xx) tag marks the end of a commit and provides a checksum for all metadata in the block.

    Integrity Details:

    • Checksum: Uses a CRC-32 with polynomial 0x04c11db7 initialized with 0xffffffff.
    • Scope: The CRC covers all metadata since the previous CRC tag, including the CRC tag itself.
    • Valid State: A 1-bit flag that determines the expected state of the valid bit for any following tags. This ensures that unwritten storage in a metadata block is detected as invalid.
    • Padding: The data field may be larger than 32 bits to pad the commit to the next program-aligned boundary.
  4. Understand littlefs Global State and Move State

    main

    littlefs uses a "global state" mechanism to track system-wide information that can be updated by committing to any metadata pair. This is achieved by distributing delta bits across the filesystem; the final state is the XOR-sum of these deltas.

    Move State (LFS_TYPE_MOVESTATE, 0x7ff): This is used to handle operations that could cause filesystem desynchronization during power loss (e.g., moving files between metadata pairs).

    • Sync Bit: If set, the metadata pair threaded linked-list is out of sync and must be checked for errors (like orphaned directories or bad blocks).
    • Move Type: Indicates if a move is in progress. 0x000 means no move; 0x4ff indicates the source file should be deleted to complete a move.
    • Move ID: The 10-bit ID of the file being moved.
    • Metadata Pair: An 8-byte pointer to the metadata pair containing the move.
  5. Use EERef and EEPtr for advanced memory manipulation

    main

    The library provides two background classes for custom memory management:

    EERef

    An EERef object acts like a single byte of RAM but is backed by EEPROM. It has a 2-byte overhead. You can create one using the subscript operator.

    EEPtr

    An EEPtr is a bidirectional pointer to EERef objects. It supports standard pointer arithmetic like increment (++) and decrement (--) operators and dereferencing (*).

    To facilitate iteration, use EEPROM.begin() to get an EEPtr pointing to the first cell, and EEPROM.end() to get an EEPtr pointing to the location after the last cell (note: EEPROM.end() points to the first cell due to hardware address wrapping).

    // EERef example
    EERef ref = EEPROM[ 10 ];
    ref = 4; // write
    unsigned char val = ref; // read
    
    // EEPtr example
    EEPtr ptr = 10;
    *ptr = 4; // dereference and write
    unsigned char val2 = *ptr; // dereference and read
    ptr++; // move to next cell
  6. How littlefs manages directories and traversal

    main

    In littlefs, directories are implemented as a tree structure where each directory is a linked-list of metadata pairs. This allows for an unlimited number of files per directory without unbounded runtime complexity.

    To solve the problem of traversing a tree structure with a constant (bounded) amount of RAM, littlefs uses a threaded linked-list. This is a separate linked-list that threads through the entire directory tree, enabling cheap, full-filesystem traversal even when RAM is limited. This approach deviates from pure Copy-on-Write (COW) operations to prioritize traversal efficiency and power resilience.

  7. Understanding orphans and half-orphans in littlefs

    main

    Because littlefs uses a threaded linked-list that is not strictly bound to the directory tree's COW operations, certain states can occur during power loss:

    • Orphaned metadata pairs: Metadata pairs that exist in the threaded linked-list but have no parent in the actual directory tree. This happens when a directory is added or removed, but the power is lost before the parent directory's pointer is updated.
    • Half-orphans: A specific type of orphan that occurs during block eviction (e.g., when a bad block is detected and a replacement is allocated). A half-orphan exists when the filesystem tree has been updated to reference a new replacement block, but the threaded linked-list still points to the old, evicted block due to an interrupted operation.

    Recovery: Finding orphans and half-orphans requires an $O(n^2)$ comparison of every metadata pair against every directory entry. To maintain performance, littlefs typically only checks for orphans during the first allocation after a boot sequence. Read-only mounts can ignore the threaded linked-list entirely.

  8. How littlefs handles atomic file moves using global state

    main

    In littlefs, moving a file between two directories cannot be done in a single atomic commit because a commit cannot span multiple directories. To prevent file duplication or loss during power-loss events, littlefs uses a mechanism called global state.

    The Mechanism: Global State

    Global state is a small set of data distributed across the filesystem as deltas (stored in metadata pairs). The actual global state is reconstructed by performing a bitwise XOR operation on all deltas found in the filesystem during the mount process.

    Solving the Move Problem

    To move a file (or directory) atomically:

    1. Begin Move: Create a new reference in the destination directory and update the global state with a delta describing the move (e.g., gstate = moving file D in dir A).
    2. Complete Move: Remove the old reference from the source directory and update the global state with a delta that cancels out the previous move delta (e.g., gstate = no move).

    Power-Loss Recovery

    If power is lost mid-move, the file may exist in both the source and destination directories. Upon the next mount, littlefs reconstructs the global state from the deltas. If the reconstructed state indicates an ongoing move, the filesystem uses that information to identify and resolve the duplication (e.g., by removing the redundant file).

  9. How CTZ Skip-Lists store large files

    main

    For files that cannot fit within a metadata pair, littlefs uses a LFS_TYPE_CTZSTRUCT (0x202) to implement a CTZ skip-list. This structure stores files in reverse using a skip-list mechanism.

    Key Mechanics:

    • For every $n$-th block where $n$ is divisible by $2^x$, the block contains a pointer to block $n-2^x$.
    • These pointers are stored in increasing order of $x$ within the block before the actual data.
    • The CTZ-struct tag contains a File head (32-bit pointer to the head of the skip-list) and the File size (32-bit).
    • Constraint: To support 32-bit file sizes, the minimum block size must be at least 104 bytes to accommodate the maximum number of pointers.
  10. How global state is updated and reconstructed in littlefs

    main

    Global state in littlefs is managed through XOR-based deltas stored within metadata pairs. This allows any metadata pair to contribute to or modify the global state.

    Updating Global State

    To update the global state from a specific metadata pair:

    1. Take the current known global state.
    2. XOR it with the desired new state.
    3. XOR that result with any existing delta currently in the metadata pair.
    4. Commit this new delta to the metadata pair.

    Reconstruction

    Because deltas are distributed, the filesystem must iterate over all metadata pairs and XOR their deltas together to build the actual global state. To maintain performance, littlefs keeps a copy of the reconstructed global state in RAM after the initial mount.

  11. Metadata block layout and iteration

    main

    A metadata block is structured as a series of commits. Each commit contains a variable number of metadata entries followed by a 32-bit CRC.

    Layout Components

    • Revision Count (32-bit): Incremented per erase cycle.
    • Entries: Metadata entries consist of a 32-bit tag followed by a variable-length data blob. Entries are not necessarily word-aligned, though writes must align with the program block size.
    • CRC (32-bit): Used to detect corruption. Uses a CRC-32 polynomial of 0x04c11db7 initialized with 0xffffffff.

    Iteration Mechanism

    To support both forward and backward iteration without duplicating tag space, neighboring entries have their tags XORed together, starting with 0xffffffff.

    • Forward Iteration: tag ~A $\rightarrow$ xor $\rightarrow$ tag A $\rightarrow$ xor $\rightarrow$ tag AxB...
    • Backward Iteration: tag ~A $\rightarrow$ xor $\rightarrow$ 0xffffffff...