-
Notifications
You must be signed in to change notification settings - Fork 51
/
littlefs_hal.c
130 lines (106 loc) · 3.59 KB
/
littlefs_hal.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/* Copyright (C) 1883 Thomas Edison - All Rights Reserved
* You may use, distribute and modify this code under the
* terms of the BSD 3 clause license, which unfortunately
* won't be written for another century.
*
* SPDX-License-Identifier: BSD-3-Clause
*
* A little flash file system for the Raspberry Pico
*
*/
// Code lifted from https://github.com/lurk101/pico-littlefs
// Modified by Terje Io for grblHAL and latest littlefs version
#include "hardware/flash.h"
#include "hardware/regs/addressmap.h"
#include "hardware/sync.h"
#include "pico/mutex.h"
#include "littlefs_hal.h"
#define FS_SIZE (512 * 1024)
typedef struct {
const char *baseaddr;
const char *nocacheaddr;
#if LFS_THREADSAFE
recursive_mutex_t fs_mtx;
#endif
} pico_lfs_context_t;
// Pico specific hardware abstraction functions
static int pico_hal_read (const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void* buffer, lfs_size_t size)
{
assert(block < c->block_count);
assert(off + size <= c->block_size);
// read flash via XIP mapped space
memcpy(buffer, ((pico_lfs_context_t *)c->context)->nocacheaddr + (block * c->block_size) + off, size);
return LFS_ERR_OK;
}
static int pico_hal_prog (const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void* buffer, lfs_size_t size)
{
assert(block < c->block_count);
// program with SDK
uint32_t p = (uint32_t)((pico_lfs_context_t *)c->context)->baseaddr + (block * c->block_size) + off;
uint32_t ints = save_and_disable_interrupts();
flash_range_program(p, buffer, size);
restore_interrupts(ints);
return LFS_ERR_OK;
}
static int pico_hal_erase (const struct lfs_config *c, lfs_block_t block)
{
assert(block < c->block_count);
// erase with SDK
uint32_t p = (uint32_t)((pico_lfs_context_t *)c->context)->baseaddr + block * c->block_size;
uint32_t ints = save_and_disable_interrupts();
flash_range_erase(p, c->block_size);
restore_interrupts(ints);
return LFS_ERR_OK;
}
static int pico_hal_sync (const struct lfs_config *c)
{
(void)c;
return LFS_ERR_OK;
}
#if LFS_THREADSAFE
static int pico_lock (const struct lfs_config *c)
{
recursive_mutex_enter_blocking(&((pico_lfs_context_t *)c->context)->fs_mtx);
return LFS_ERR_OK;
}
static int pico_unlock (const struct lfs_config *c)
{
recursive_mutex_exit(&((pico_lfs_context_t *)c->context)->fs_mtx);
return LFS_ERR_OK;
}
#endif
struct lfs_config *pico_littlefs_hal (void)
{
// File system offsets in flash
static pico_lfs_context_t ctx = {
.baseaddr = (const char *)(PICO_FLASH_SIZE_BYTES - FS_SIZE - (32 * 1024)),
.nocacheaddr = (const char *)(XIP_NOCACHE_NOALLOC_BASE + PICO_FLASH_SIZE_BYTES - FS_SIZE - (32 * 1024))
};
// Configuration of the filesystem is provided by this struct
// for Pico: prog size = 256, block size = 4096, so cache is 8K
// minimum cache = block size, must be multiple
static struct lfs_config pico_cfg = {
.context = &ctx,
// block device operations
.read = pico_hal_read,
.prog = pico_hal_prog,
.erase = pico_hal_erase,
.sync = pico_hal_sync,
#if LFS_THREADSAFE
.lock = pico_lock,
.unlock = pico_unlock,
#endif
// block device configuration
.read_size = 1,
.prog_size = FLASH_PAGE_SIZE,
.block_size = FLASH_SECTOR_SIZE,
.block_count = FS_SIZE / FLASH_SECTOR_SIZE,
.cache_size = FLASH_SECTOR_SIZE / 4,
.lookahead_size = 32,
.block_cycles = 500
};
#if LFS_THREADSAFE
recursive_mutex_init(&ctx.fs_mtx);
#endif
return &pico_cfg;
}