ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_fs_fat_space.c
Go to the documentation of this file.
1
35
36#include <stddef.h>
37#include <stdint.h>
38
39#include "ra8_attributes.h"
40#include "ra8_fs.h"
41#include "ra8_fs_fat_internal.h"
42#include "ra8_fs_meta.h"
43
60
84static uint32_t internal_popcount8(uint8_t b)
85{
86 uint32_t n = 0U;
87 for (uint32_t i = 0U; i < (uint32_t)k_space_bits_per_byte; i++) {
88 n += ((uint32_t)b >> i) & 1U;
89 }
90 return n;
91}
92
119static ra8_err_t internal_space_fat_free(const ra8_fs_mount_t* m, uint32_t* out_free)
120{
121 uint32_t free = 0U;
122 const uint32_t last = (uint32_t)k_cluster_first_data + m->count_of_clusters;
123 for (uint32_t c = (uint32_t)k_cluster_first_data; c < last; c++) {
124 uint32_t v = 0U;
125 const ra8_err_t err = priv_fat_get(m, c, &v);
126 if (err != k_ra8_ok) {
127 return err;
128 }
129 if (v == (uint32_t)k_cluster_free) {
130 free++;
131 }
132 }
133 *out_free = free;
134 return k_ra8_ok;
135}
136
166static ra8_err_t internal_space_exfat_free(const ra8_fs_mount_t* m, uint32_t* out_free)
167{
168 uint32_t bmp_clus = 0U;
169 uint32_t bmp_len = 0U;
170 const ra8_err_t ferr = priv_exfat_find_bitmap(m, &bmp_clus, &bmp_len);
171 if (ferr != k_ra8_ok) {
172 return ferr;
173 }
174 const uint64_t bmp_lba = priv_cluster_to_lba(m, bmp_clus);
175 const uint32_t total = m->count_of_clusters;
176 const uint32_t full_bytes = total >> (uint32_t)k_space_byte_shift;
177 const uint32_t rem_bits = total & (uint32_t)k_space_bit_mask;
178 /* One byte per full group of 8 clusters, plus one partial byte for the tail.
179 * The tail byte is masked to the volume's last cluster so any bits the spec
180 * leaves 0 past the heap cannot inflate the used count. */
181 const uint32_t nbytes = full_bytes + ((rem_bits != 0U) ? 1U : 0U);
182 uint32_t used = 0U;
183 uint64_t loaded = UINT64_MAX;
184 uint8_t* const sec = priv_sec_io();
185 for (uint32_t bi = 0U; bi < nbytes; bi++) {
186 const uint64_t lba = bmp_lba + (bi / priv_bps(m));
187 if (lba != loaded) {
188 const ra8_err_t err = priv_read_sector(m, lba, sec);
189 if (err != k_ra8_ok) {
190 return err;
191 }
192 loaded = lba;
193 }
194 uint8_t b = sec[bi % priv_bps(m)];
195 /* The loop only reaches `bi == full_bytes` when `rem_bits != 0` (that is the
196 * only case `nbytes` includes the partial byte), so masking it here needs no
197 * second condition -- and adding one would be an MC/DC hole nothing can flip. */
198 if (bi == full_bytes) {
199 b = (uint8_t)(b & (uint8_t)((1U << rem_bits) - 1U));
200 }
201 used += internal_popcount8(b);
202 }
203 /* The bitmap holds exactly `total` cluster bits and the tail is masked, so
204 * `used <= total` always -- no clamp needed. */
205 *out_free = total - used;
206 return k_ra8_ok;
207}
208
241static ra8_err_t internal_space_free_clusters(const ra8_fs_mount_t* m, uint32_t* out_free)
242{
243 if (m->type == k_ra8_fs_type_exfat) {
244 return internal_space_exfat_free(m, out_free);
245 }
246 const uint32_t cached = priv_free_count_peek(m);
247 if (cached != (uint32_t)k_fs_free_unknown) {
248 *out_free = cached;
249 return k_ra8_ok;
250 }
251 const ra8_err_t err = internal_space_fat_free(m, out_free);
252 if (err != k_ra8_ok) {
253 return err;
254 }
255 priv_free_count_cache(m, *out_free);
256 return k_ra8_ok;
257}
258
289RA8_EXPECTS_LOCK("ra8_fs_lock")
291{
292 if (handle == nullptr || out == nullptr) {
293 return k_ra8_err_null_ptr;
294 }
295 if (handle->in_use == 0U) {
296 return k_ra8_err_invalid_state;
297 }
298 uint32_t free_clusters = 0U;
299 const ra8_err_t err = internal_space_free_clusters(handle, &free_clusters);
300 if (err != k_ra8_ok) {
301 return err;
302 }
303 /* `free_clusters` is bounded by the volume size at its source: the FAT scan
304 * counts among exactly `count_of_clusters` entries, the bitmap popcount masks
305 * to the last cluster, and the cached count is clamped on the way in. So no
306 * clamp is needed here. */
307 const uint32_t total = handle->count_of_clusters;
308 const uint32_t bytes_per_cluster = priv_cluster_bytes(handle);
309 const uint32_t used = total - free_clusters;
310 *out = (ra8_fs_space_t){};
311 out->bytes_per_cluster = bytes_per_cluster;
312 out->total_clusters = total;
313 out->free_clusters = free_clusters;
314 out->used_clusters = used;
315 out->total_bytes = (uint64_t)total * (uint64_t)bytes_per_cluster;
316 out->free_bytes = (uint64_t)free_clusters * (uint64_t)bytes_per_cluster;
317 out->used_bytes = (uint64_t)used * (uint64_t)bytes_per_cluster;
318 return k_ra8_ok;
319}
320
321/* =============================================================================
322 * Public entry point -- the lock bracket
323 * =============================================================================
324 */
325
326RA8_OWNS_RESOURCE("ra8_fs_lock")
328{
330 const ra8_err_t err = internal_space_locked(handle, out);
332 return err;
333}
Annotation-attribute framework macros for ra8-firmware.
#define RA8_OWNS_RESOURCE(kind)
RAII-style resource ownership contract.
#define RA8_EXPECTS_LOCK(name)
The function expects the named thread/IRQ lock to be held on entry.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
Definition ra8_err.h:478
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Minimal FAT12/FAT16/FAT32 filesystem adapter (read + write).
ra8_err_t priv_fat_get(const ra8_fs_mount_t *m, uint32_t cluster, uint32_t *out_value)
Fetch the FAT entry for cluster, returning the next-cluster value.
Definition ra8_fs_fat.c:187
uint64_t priv_cluster_to_lba(const ra8_fs_mount_t *m, uint32_t cluster)
Convert a cluster number into its first data-region LBA.
Definition ra8_fs_fat.c:541
ra8_err_t priv_read_sector(const ra8_fs_mount_t *m, uint64_t lba, uint8_t *buf)
Read a single sector into the module scratch buffer.
Definition ra8_fs_fat.c:134
uint32_t priv_bps(const ra8_fs_mount_t *m)
One mounted volume's sector size in bytes.
Definition ra8_fs_fat.c:84
uint32_t priv_cluster_bytes(const ra8_fs_mount_t *m)
One mounted volume's cluster size in bytes.
Definition ra8_fs_fat.c:90
uint32_t priv_free_count_peek(const ra8_fs_mount_t *m)
Report the tracked free-cluster count, or k_fs_free_unknown.
void priv_free_count_cache(const ra8_fs_mount_t *m, uint32_t n)
Cache a freshly counted free-cluster total in the allocator slot.
@ k_fs_free_unknown
MS FAT spec sec 5: count not known.
uint8_t * priv_sec_io(void)
The IO-role sector buffer (leaf data / bitmap sector transfers).
ra8_err_t priv_exfat_find_bitmap(const ra8_fs_mount_t *m, uint32_t *out_clus, uint32_t *out_len)
Locate the allocation-bitmap entry in the exFAT root directory.
Cross-TU shared declarations for the FAT/exFAT ra8_fs adapter.
void priv_lock_release(void)
Drop the library lock taken by priv_lock_acquire.
void priv_lock_acquire(void)
Take the library lock, if the caller installed one.
static ra8_err_t internal_space_free_clusters(const ra8_fs_mount_t *m, uint32_t *out_free)
Resolve the free-cluster count: cached, or freshly walked and cached.
static ra8_err_t internal_space_exfat_free(const ra8_fs_mount_t *m, uint32_t *out_free)
Count free clusters on an exFAT volume by population-counting the bitmap.
ra8_fs_space_const_t
Bit-arithmetic constants for the free-space walkers.
@ k_space_bit_mask
Cluster index -> bit within its byte.
@ k_space_byte_shift
log2(8): cluster index -> bitmap byte.
@ k_space_bits_per_byte
Bits in one allocation-bitmap byte.
static ra8_err_t internal_space_fat_free(const ra8_fs_mount_t *m, uint32_t *out_free)
Count free clusters on a FAT12/16/32 volume by scanning the FAT.
static ra8_err_t internal_space_locked(const ra8_fs_mount_t *handle, ra8_fs_space_t *out)
Report free/used/total space – the guarded body of ra8_fs_free_space().
static uint32_t internal_popcount8(uint8_t b)
Count the set bits in one byte.
@ k_cluster_free
Cluster free.
@ k_cluster_first_data
Cluster numbers start at 2.
Volume-level metadata: free space, volume label, and per-entry utime.
ra8_err_t ra8_fs_free_space(const ra8_fs_mount_t *handle, ra8_fs_space_t *out)
Report a mounted volume's total, free, and used space.
@ k_ra8_fs_type_exfat
exFAT (read + streaming write + format).
Cached parse of one mounted FAT volume.
ra8_fs_type_t type
FAT12 / FAT16 / FAT32.
uint32_t count_of_clusters
Per MS spec: data_sectors / SPC.
A mounted volume's capacity, free space, and cluster geometry.
Definition ra8_fs_meta.h:84