Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

massdrop alt/ctrl: support saving into nvm #6068

Merged
merged 5 commits into from
Sep 29, 2021
Merged
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
94 changes: 90 additions & 4 deletions tmk_core/common/arm_atsam/eeprom.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,110 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "eeprom.h"
#include "debug.h"
#include "samd51j18a.h"
#include "core_cm4.h"
#include "component/nvmctrl.h"

#ifndef EEPROM_SIZE
# include "eeconfig.h"
# define EEPROM_SIZE (((EECONFIG_SIZE + 3) / 4) * 4) // based off eeconfig's current usage, aligned to 4-byte sizes, to deal with LTO
#endif

__attribute__((aligned(4))) static uint8_t buffer[EEPROM_SIZE];
#ifndef MAX
# define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
#endif

#ifndef BUSY_RETRIES
# define BUSY_RETRIES 10000
#endif

// #define DEBUG_EEPROM_OUTPUT

/*
* Debug print utils
*/
#if defined(DEBUG_EEPROM_OUTPUT)
# define eeprom_printf(fmt, ...) xprintf(fmt, ##__VA_ARGS__);
#else /* NO_DEBUG */
# define eeprom_printf(fmt, ...)
#endif /* NO_DEBUG */

__attribute__((aligned(4))) static uint8_t buffer[EEPROM_SIZE] = {0};
volatile uint8_t * SmartEEPROM8 = (uint8_t *)SEEPROM_ADDR;

static inline bool eeprom_is_busy(void) {
int timeout = BUSY_RETRIES;
while (NVMCTRL->SEESTAT.bit.BUSY && timeout-- > 0)
;

return NVMCTRL->SEESTAT.bit.BUSY;
}

static uint32_t get_virtual_eeprom_size(void) {
// clang-format off
static const uint32_t VIRTUAL_EEPROM_MAP[11][8] = {
/* 4 8 16 32 64 128 256 512 */
/* 0*/ { 0, 0, 0, 0, 0, 0, 0, 0 },
/* 1*/ { 512, 1024, 2048, 4096, 4096, 4096, 4096, 4096 },
/* 2*/ { 512, 1024, 2048, 4096, 8192, 8192, 8192, 8192 },
/* 3*/ { 512, 1024, 2048, 4096, 8192, 16384, 16384, 16384 },
/* 4*/ { 512, 1024, 2048, 4096, 8192, 16384, 16384, 16384 },
/* 5*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 32768 },
/* 6*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 32768 },
/* 7*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 32768 },
/* 8*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 32768 },
/* 9*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536 },
/*10*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536 },
};
// clang-format on

static uint32_t virtual_eeprom_size = UINT32_MAX;
if (virtual_eeprom_size == UINT32_MAX) {
virtual_eeprom_size = VIRTUAL_EEPROM_MAP[NVMCTRL->SEESTAT.bit.PSZ][NVMCTRL->SEESTAT.bit.SBLK];
}
// eeprom_printf("get_virtual_eeprom_size:: %d:%d:%d\n", NVMCTRL->SEESTAT.bit.PSZ, NVMCTRL->SEESTAT.bit.SBLK, virtual_eeprom_size);
return virtual_eeprom_size;
}

uint8_t eeprom_read_byte(const uint8_t *addr) {
uintptr_t offset = (uintptr_t)addr;
return buffer[offset];
if (offset >= MAX(EEPROM_SIZE, get_virtual_eeprom_size())) {
eeprom_printf("eeprom_read_byte:: out of bounds\n");
return 0x0;
}

if (get_virtual_eeprom_size() == 0) {
return buffer[offset];
}

if (eeprom_is_busy()) {
eeprom_printf("eeprom_write_byte:: timeout\n");
return 0x0;
}

return SmartEEPROM8[offset];
}

void eeprom_write_byte(uint8_t *addr, uint8_t value) {
uintptr_t offset = (uintptr_t)addr;
buffer[offset] = value;
if (offset >= MAX(EEPROM_SIZE, get_virtual_eeprom_size())) {
eeprom_printf("eeprom_write_byte:: out of bounds\n");
return;
}

if (get_virtual_eeprom_size() == 0) {
buffer[offset] = value;
return;
}

if (eeprom_is_busy()) {
eeprom_printf("eeprom_write_byte:: timeout\n");
return;
}

SmartEEPROM8[offset] = value;
}

uint16_t eeprom_read_word(const uint16_t *addr) {
Expand Down