cpu/sam0_common: flashpage: introduce functions to write to user page
This commit is contained in:
parent
360c0b27fc
commit
20f093ede6
@ -1095,6 +1095,78 @@ int rtc_tamper_register(gpio_t pin, gpio_flank_t flank);
|
|||||||
void rtc_tamper_enable(void);
|
void rtc_tamper_enable(void);
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name sam0 User Configuration
|
||||||
|
*
|
||||||
|
* The MCUs of this family contain a region of memory that is used to store
|
||||||
|
* CPU configuration & calibration data.
|
||||||
|
* It can be used to set persistent settings and has some additional space
|
||||||
|
* to store user configuration data.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief MCU configuration applied on start. The contents of this struct differ
|
||||||
|
* between families.
|
||||||
|
*/
|
||||||
|
typedef struct sam0_aux_cfg_mapping nvm_user_page_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Size of the free to use auxiliary area in the user page
|
||||||
|
*/
|
||||||
|
#ifdef FLASH_USER_PAGE_SIZE
|
||||||
|
#define FLASH_USER_PAGE_AUX_SIZE (FLASH_USER_PAGE_SIZE - sizeof(nvm_user_page_t))
|
||||||
|
#else
|
||||||
|
#define FLASH_USER_PAGE_AUX_SIZE (AUX_PAGE_SIZE * AUX_NB_OF_PAGES - sizeof(nvm_user_page_t))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset the configuration area, apply a new configuration.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param cfg New MCU configuration, may be NULL.
|
||||||
|
* If cfg is NULL, this will clear the configuration area
|
||||||
|
* and apply the current configuration again.
|
||||||
|
*/
|
||||||
|
void sam0_flashpage_aux_reset(const nvm_user_page_t *cfg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write data to the user configuration area.
|
||||||
|
* This will write data to the remaining space after @see nvm_user_page_t
|
||||||
|
* The size of this area depends on the MCU family used.
|
||||||
|
*
|
||||||
|
* Will only write bits 1 -> 0. To reset bits to 1, call @see sam0_flashpage_aux_reset
|
||||||
|
* This will reset the whole user area configuration.
|
||||||
|
*
|
||||||
|
* Arbitrary data lengths and offsets are supported.
|
||||||
|
*
|
||||||
|
* @param offset Byte offset after @see nvm_user_page_t
|
||||||
|
* must be less than `FLASH_USER_PAGE_AUX_SIZE`
|
||||||
|
* @param data The data to write
|
||||||
|
* @param len Size of the data
|
||||||
|
*/
|
||||||
|
void sam0_flashpage_aux_write_raw(uint32_t offset, const void *data, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get pointer to data in the user configuration area.
|
||||||
|
*
|
||||||
|
* @param offset Byte offset after @see nvm_user_page_t
|
||||||
|
* must be less than `FLASH_USER_PAGE_AUX_SIZE`
|
||||||
|
* @return Pointer to the data in the User Page
|
||||||
|
*/
|
||||||
|
#define sam0_flashpage_aux_get(offset) \
|
||||||
|
(const void*)((uint8_t*)NVMCTRL_USER + sizeof(nvm_user_page_t) + (offset))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get pointer to data in the CPU configuration struct
|
||||||
|
*
|
||||||
|
* @return Pointer to the @ref nvm_user_page_t structure
|
||||||
|
*/
|
||||||
|
#define sam0_flashpage_aux_cfg() \
|
||||||
|
((const nvm_user_page_t*)NVMCTRL_USER)
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "periph/flashpage.h"
|
#include "periph/flashpage.h"
|
||||||
@ -36,6 +37,15 @@
|
|||||||
|
|
||||||
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||||
|
|
||||||
|
/* Write Quad Word is the only allowed operation on AUX pages */
|
||||||
|
#if defined(NVMCTRL_CTRLB_CMD_WQW)
|
||||||
|
#define AUX_CHUNK_SIZE (4 * sizeof(uint32_t))
|
||||||
|
#elif defined(AUX_PAGE_SIZE)
|
||||||
|
#define AUX_CHUNK_SIZE AUX_PAGE_SIZE
|
||||||
|
#else
|
||||||
|
#define AUX_CHUNK_SIZE FLASH_USER_PAGE_SIZE
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief NVMCTRL selection macros
|
* @brief NVMCTRL selection macros
|
||||||
*/
|
*/
|
||||||
@ -87,6 +97,21 @@ static void _cmd_clear_page_buffer(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _cmd_erase_aux(void)
|
||||||
|
{
|
||||||
|
wait_nvm_is_ready();
|
||||||
|
|
||||||
|
/* send Erase Page/Auxiliary Row command */
|
||||||
|
#if defined(NVMCTRL_CTRLB_CMD_EP)
|
||||||
|
_NVMCTRL->CTRLB.reg = (NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_EP);
|
||||||
|
#elif defined(NVMCTRL_CTRLA_CMD_EAR)
|
||||||
|
_NVMCTRL->CTRLA.reg = (NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_EAR);
|
||||||
|
#else
|
||||||
|
/* SAML1x uses same command for all areas */
|
||||||
|
_NVMCTRL->CTRLA.reg = (NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void _cmd_erase_row(void)
|
static void _cmd_erase_row(void)
|
||||||
{
|
{
|
||||||
wait_nvm_is_ready();
|
wait_nvm_is_ready();
|
||||||
@ -99,6 +124,21 @@ static void _cmd_erase_row(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _cmd_write_aux(void)
|
||||||
|
{
|
||||||
|
wait_nvm_is_ready();
|
||||||
|
|
||||||
|
/* write auxiliary page */
|
||||||
|
#if defined(NVMCTRL_CTRLA_CMD_WAP)
|
||||||
|
_NVMCTRL->CTRLA.reg = (NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WAP);
|
||||||
|
#elif defined(NVMCTRL_CTRLB_CMD_WQW)
|
||||||
|
_NVMCTRL->CTRLB.reg = (NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_WQW);
|
||||||
|
#else
|
||||||
|
/* SAML1x uses same command for all areas */
|
||||||
|
_NVMCTRL->CTRLA.reg = (NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void _cmd_write_page(void)
|
static void _cmd_write_page(void)
|
||||||
{
|
{
|
||||||
wait_nvm_is_ready();
|
wait_nvm_is_ready();
|
||||||
@ -202,7 +242,32 @@ void flashpage_write_raw(void *target_addr, const void *data, size_t len)
|
|||||||
(CPU_FLASH_BASE + (FLASHPAGE_SIZE * FLASHPAGE_NUMOF)));
|
(CPU_FLASH_BASE + (FLASHPAGE_SIZE * FLASHPAGE_NUMOF)));
|
||||||
|
|
||||||
_write_page(target_addr, data, len, _cmd_write_page);
|
_write_page(target_addr, data, len, _cmd_write_page);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sam0_flashpage_aux_write_raw(uint32_t offset, const void *data, size_t len)
|
||||||
|
{
|
||||||
|
uintptr_t dst = NVMCTRL_USER + sizeof(nvm_user_page_t) + offset;
|
||||||
|
|
||||||
|
#ifdef FLASH_USER_PAGE_SIZE
|
||||||
|
assert(dst + len <= NVMCTRL_USER + FLASH_USER_PAGE_SIZE);
|
||||||
|
#else
|
||||||
|
assert(dst + len <= NVMCTRL_USER + AUX_PAGE_SIZE * AUX_NB_OF_PAGES);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_write_row((void*)dst, data, len, AUX_CHUNK_SIZE, _cmd_write_aux);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sam0_flashpage_aux_reset(const nvm_user_page_t *cfg)
|
||||||
|
{
|
||||||
|
nvm_user_page_t old_cfg;
|
||||||
|
|
||||||
|
if (cfg == NULL) {
|
||||||
|
cfg = &old_cfg;
|
||||||
|
memcpy(&old_cfg, (void*)NVMCTRL_USER, sizeof(*cfg));
|
||||||
|
}
|
||||||
|
|
||||||
|
_erase_page((void*)NVMCTRL_USER, _cmd_erase_aux);
|
||||||
|
_write_row((void*)NVMCTRL_USER, cfg, sizeof(*cfg), AUX_CHUNK_SIZE, _cmd_write_aux);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FLASHPAGE_RWWEE_NUMOF
|
#ifdef FLASHPAGE_RWWEE_NUMOF
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user