Skip to content

OSAL Firmware update implementation for EFR32 Wi-SUN #30

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

Open
wants to merge 46 commits into
base: osal
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
560210f
OSAL APIs to read/write firmware
manojnacsl Dec 12, 2024
248dd03
Cleanup
manojnacsl Dec 12, 2024
0987135
Remove unecessary return statements from csmptlvs post handler
ismilak Jan 24, 2025
2c73770
Fix slot header access in osal_write_firmware in linx port
ismilak Jan 24, 2025
9e76267
Fix ef32_wisun builds
ismilak Feb 5, 2025
ac05f03
Fix FreeRTOS build
ismilak Feb 5, 2025
7430b57
Remvoe image storage from Csmp_Slothdr for EFR32 wisun, since the ima…
ismilak Feb 5, 2025
53c6629
Add read/write firmware skeleton for efr32_wisun osal
ismilak Feb 5, 2025
f7da5af
Refactor csmp slot header handling and osal
ismilak Feb 5, 2025
8adb61a
Add debug codes
ismilak Feb 14, 2025
423a03e
Write image chunks to the external flash with gecko bootloader API
ismilak Feb 14, 2025
8a20e9b
Add write image API call to lrq timer fired and backup post request
ismilak Feb 14, 2025
2c7fb1c
Enable read fw calls for all platforms
ismilak Feb 14, 2025
2e2a63a
Add nvm3 read write
ismilak Feb 17, 2025
38d20d0
Introduce copy firmware slot and deploy and reboot osal APIs
ismilak Feb 18, 2025
3991ddc
Remove debug print header
ismilak Feb 18, 2025
0ab3a6b
Remove hard-coded sisdk version from sample/efr32_wisun.target
ismilak Feb 20, 2025
bb05b87
Fix get time API usage for having functional load request timer
ismilak Feb 20, 2025
621980e
Add storage slot assertion
ismilak Feb 25, 2025
2781b1d
Add destination slot erase to the copy slot API
ismilak Feb 25, 2025
6c07fa9
Add bootloader erase upload storage call to the transfer POST request
ismilak Feb 25, 2025
7d63b2b
Rename defines in osal header to add 'osal' prefix
ismilak Feb 26, 2025
ee6d6ef
Refactor copy slot: copy header content to nvm3 only after a succesfu…
ismilak Feb 26, 2025
84e0d22
Rename osal read/write firmware to 'read/write firmware header' to al…
ismilak Feb 26, 2025
00b2c94
Remove unecessary gecko bootloader call
ismilak Feb 26, 2025
a1f2c9e
Implemente write slot OSAL API to make slot read/write operation expl…
ismilak Feb 26, 2025
aa3c9b1
Implement erease slot OSAL API to avoid using gecko bootloader platfo…
ismilak Feb 26, 2025
82a129c
Clean efr32 tlvs and osal port
ismilak Feb 26, 2025
c57c0a2
Use copy firmware OSAL API in freertos and linux tlvs
ismilak Feb 26, 2025
ac91ef9
Use reboot and install in freertos and linux tlvs
ismilak Feb 26, 2025
6a05e1e
Fix linux and freertos debug print warnings in TLVs and OSAL
ismilak Feb 27, 2025
2f37d12
Fix memory leak in image block post request handling in 'csmp_firmwar…
ismilak Mar 24, 2025
9d6d8d9
Increase the EFR32 wisun threads priority to 'normal' (CMSIS RTOS sym…
ismilak Mar 24, 2025
c58efe3
Add missing string.h include to 'osal_efr32_wisun.c'
ismilak Mar 24, 2025
1c9b964
Store header in image block post handler after each 10th block
ismilak Mar 25, 2025
e0f06b3
Restore OSAL content for linux
ismilak Jun 5, 2025
7f69ea1
Fix osal and related changes
ismilak Jun 6, 2025
fe184aa
Make efr32_wisun buildable
ismilak Jun 6, 2025
b4ba117
Fix FreeRTOS
ismilak Jun 6, 2025
62c0931
Fix sample app
ismilak Jun 8, 2025
d4eb676
Fix sample tlvs
ismilak Jun 8, 2025
cef904c
Fix csmp_firmwareMgmt.c meamleak
ismilak Jun 8, 2025
8461dc6
Remove osal reboot and deploy API and replace with gecko bootloader c…
ismilak Jun 8, 2025
6ce4069
Add Chip reset call to efr32 osal_system_reboot
ismilak Jun 8, 2025
bd77d6f
Fix init run slot with default data
ismilak Jun 9, 2025
94cb6fb
Make efr32 backward compatible
ismilak Jun 10, 2025
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
build/
sample/CsmpAgentLib_sample
sample/CsmpAgentLib_sample.bin
efr32_wisun/build/
*.o
*.a
Expand Down
1 change: 1 addition & 0 deletions efr32_wisun.target
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ INCLUDES += -Iinclude\

C_FLAGS += -Wno-missing-braces
C_FLAGS_DEBUG =
# C_FLAGS_DEBUG += -DPRINTDEBUG
C_FLAGS_RELEASE =
CXX_FLAGS =
CXX_FLAGS_DEBUG =
Expand Down
314 changes: 300 additions & 14 deletions osal/efr32_wisun/osal_efr32_wisun.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,28 @@
* limitations under the License.
*/

#include <string.h>
#include "osal.h"
#include "../../src/lib/debug.h"
#include "nvm3.h"
#include "nvm3_hal_flash.h"
#include "btl_interface.h"
#include "sl_component_catalog.h"

#if defined(SL_CATALOG_SL_MAIN_PRESENT)
#include "sl_main_kernel.h"
#else
#include "sl_system_kernel.h"
#endif

#define OSAL_EFR32_WISUN_MIN_STACK_SIZE_WORDS 4096

#define OSAL_EFR32_WISUN_NVM_KEY_BASE 0x00000F0
#define OSAL_EFR32_WISUN_NVM_KEY_RUN_IMG (OSAL_EFR32_WISUN_NVM_KEY_BASE + 0x0000U)
#define OSAL_EFR32_WISUN_NVM_KEY_UPLOAD_IMG (OSAL_EFR32_WISUN_NVM_KEY_BASE + 0x0001U)
#define OSAL_EFR32_WISUN_NVM_KEY_BACKUP_IMG (OSAL_EFR32_WISUN_NVM_KEY_BASE + 0x0002U)
#define GECKO_BTL_SLOT_CPY_CHUNK_SIZE 1024U

struct trickle_timer {
uint32_t t0;
uint32_t tfire;
Expand All @@ -32,6 +48,8 @@ struct trickle_timer {

#define __ret_freertos2posix(ret) \
(ret == pdPASS ? OSAL_SUCCESS : OSAL_FAILURE)
#define __slotid2gblslotid(slotid) \
(slotid == UPLOAD_IMAGE ? GECKO_BTL_UPLOAD_SLOT_ID : GECKO_BTL_BACKUP_SLOT_ID)

extern uint8_t g_csmplib_eui64[8];

Expand All @@ -44,23 +62,40 @@ static bool m_timert_isrunning = false;
static void osal_update_timer();
static void osal_alarm_fired(TimerHandle_t xTimer);
static void osal_alarm_fired_pend_fnc(void * param1, uint32_t param2);

static void osal_print_csmp_slot_hdr(const Csmp_Slothdr *slot_hdr);

void osal_kernel_start(void)
{
for (BaseType_t i = 0; i < timer_num; i++) {
timers[i].is_running = false;
timers[i].timer = xTimerCreate("trickle_timer",
pdMS_TO_TICKS(m_remaining * 1000),
pdTRUE,
(void *)i,
osal_alarm_fired);
assert(timers[i].timer != NULL);
xTimerStop(timers[i].timer, 0);

}
static BootloaderStorageInformation_t storage_info = { 0U };
static BootloaderStorageSlot_t slot_info = { 0U };

for (BaseType_t i = 0; i < timer_num; i++) {
timers[i].is_running = false;
timers[i].timer = xTimerCreate("trickle_timer",
pdMS_TO_TICKS(m_remaining * 1000),
pdTRUE,
(void *)i,
osal_alarm_fired);
assert(timers[i].timer != NULL);
xTimerStop(timers[i].timer, 0);
}

// Check bootloader storage slots
bootloader_getStorageInfo(&storage_info);

assert(storage_info.numStorageSlots >= 2);
assert(bootloader_getStorageSlotInfo(__slotid2gblslotid(UPLOAD_IMAGE),
&slot_info) == BOOTLOADER_OK);
assert(slot_info.length >= CSMP_FWMGMT_SLOTIMG_SIZE);

sl_system_kernel_start();
assert(bootloader_getStorageSlotInfo(__slotid2gblslotid(BACKUP_IMAGE),
&slot_info) == BOOTLOADER_OK);
assert(slot_info.length >= CSMP_FWMGMT_SLOTIMG_SIZE);
#if defined(SL_CATALOG_SL_MAIN_PRESENT)
sl_main_kernel_start();
#else
sl_system_kernel_start();
#endif
}

osal_basetype_t osal_task_create(osal_task_t * thread,
Expand All @@ -75,7 +110,7 @@ osal_basetype_t osal_task_create(osal_task_t * thread,
name,
(OSAL_EFR32_WISUN_MIN_STACK_SIZE_WORDS + stacksize),
arg,
priority,
23 + priority,
thread);

return __ret_freertos2posix(ret);
Expand Down Expand Up @@ -483,3 +518,254 @@ static void osal_alarm_fired_pend_fnc(void * param1, uint32_t param2)
(void) param2;
osal_alarm_fired(NULL);
}


static void osal_print_csmp_slot_hdr(const Csmp_Slothdr *slot_hdr)
{
if (slot_hdr == NULL) {
return;
}

DPRINTF("filehash: ");
for (int i = 0; i < SHA256_HASH_SIZE; i++) {
DPRINTF("%02x,", slot_hdr->filehash[i]);
}
DPRINTF("\n");
DPRINTF("filename: %s\n", slot_hdr->filename);
DPRINTF("version: %s\n", slot_hdr->version);
DPRINTF("hwid: %s\n", slot_hdr->hwid);
DPRINTF("filesize: %lu\n", slot_hdr->filesize);
DPRINTF("blocksize: %lu\n", slot_hdr->blocksize);
DPRINTF("reportintervalmin: %lu\n", slot_hdr->reportintervalmin);
DPRINTF("reportintervalmax: %lu\n", slot_hdr->reportintervalmax);
DPRINTF("status: 0x%08lx\n", slot_hdr->status);
DPRINTF("nblkmap: ");
for (int i = 0; i < CSMP_FWMGMT_BLKMAP_CNT; i++) {
DPRINTF("%08lx%c", slot_hdr->nblkmap[i],
((i % 4) == 3 || i == (CSMP_FWMGMT_BLKMAP_CNT - 1)) ? '\n' : ',');
}
DPRINTF("\n");
}

osal_basetype_t osal_read_slothdr(uint8_t slotid, Csmp_Slothdr *slot)
{
sl_status_t ret = SL_STATUS_FAIL;
nvm3_ObjectKey_t nvm_key = 0UL;
uint32_t nvm_type = 0UL;
size_t nvm_size = 0UL;

if (slot == NULL) {
return OSAL_FAILURE;
}

switch(slotid) {
case RUN_IMAGE:
printf("Reading Run Slot:\n");
nvm_key = OSAL_EFR32_WISUN_NVM_KEY_RUN_IMG;
break;
case UPLOAD_IMAGE:
printf("Reading Upload Slot:\n");
nvm_key = OSAL_EFR32_WISUN_NVM_KEY_UPLOAD_IMG;
break;
case BACKUP_IMAGE:
printf("Reading Backup Slot:\n");
nvm_key = OSAL_EFR32_WISUN_NVM_KEY_BACKUP_IMG;
break;
default:
printf("read_firmware: Invalid slot id\n");
return OSAL_FAILURE;
}

ret = nvm3_getObjectInfo(nvm3_defaultHandle, nvm_key, &nvm_type, &nvm_size);
if (ret != SL_STATUS_OK) {
printf("nvm3_getObjectInfo failed\n");
return OSAL_FAILURE;
}

ret = nvm3_readData(nvm3_defaultHandle, nvm_key, slot, nvm_size);
osal_print_csmp_slot_hdr(slot);

if (ret != SL_STATUS_OK) {
printf("nvm3_readData failed\n");
return OSAL_FAILURE;
}

return OSAL_SUCCESS;
}

osal_basetype_t osal_write_slothdr(uint8_t slotid, Csmp_Slothdr *slot)
{
sl_status_t ret = SL_STATUS_OK;
nvm3_ObjectKey_t nvm_key = 0UL;

if (slot == NULL) {
return OSAL_FAILURE;
}
switch(slotid) {
case RUN_IMAGE:
printf("Writing Run Slot:\n");
nvm_key = OSAL_EFR32_WISUN_NVM_KEY_RUN_IMG;
break;
case UPLOAD_IMAGE:
printf("Writing Upload Slot:\n");
nvm_key = OSAL_EFR32_WISUN_NVM_KEY_UPLOAD_IMG;
break;
case BACKUP_IMAGE:
printf("Writing Backup Slot:\n");
nvm_key = OSAL_EFR32_WISUN_NVM_KEY_BACKUP_IMG;
break;
default:
printf("read_firmware: Invalid slot id\n");
return OSAL_FAILURE;
}
osal_print_csmp_slot_hdr(slot);

ret = nvm3_writeData(nvm3_defaultHandle, nvm_key, slot, sizeof(Csmp_Slothdr));
if (ret != SL_STATUS_OK) {
printf("nvm3_write failed\n");
return OSAL_FAILURE;
}
return OSAL_SUCCESS;
}
/****************************************************************************
* @fn osal_read_firmware
*
* @brief read firmware image from storage(file/flash)
*
* input parameters
* @param[in] slotid indicating RUN/UPLOAD/BACKUP slot
* @param[in] data pointer to uint8_t data array
* @param[in] size of data in bytes
*
* output parameters
* @return returns 0 on success and -1 on error
*****************************************************************************/
osal_basetype_t osal_read_firmware(uint8_t slotid, uint8_t *data, uint32_t size)
{
(void) slotid;
(void) data;
(void) size;
DPRINTF("osal_read_firmware: Not implemented for EFR32 Wisun platform\n");
return OSAL_FAILURE;
}

/****************************************************************************
* @fn osal_write_firmware
*
* @brief write firmware image to storage(file/flash)
*
* input parameters
* @param[in] slotid indicating RUN/UPLOAD/BACKUP slot
* @param[in] data pointer to uint8_t data array
* @param[in] size of data in bytes
*
* output parameters
* @return returns 0 on success and -1 on error
*****************************************************************************/
osal_basetype_t osal_write_firmware(uint8_t slotid, uint8_t *data, uint32_t size)
{
(void) slotid;
(void) data;
(void) size;
DPRINTF("osal_write_firmware: Not implemented for EFR32 Wisun platform\n");
return OSAL_FAILURE;
}

osal_basetype_t osal_system_reboot(struct in6_addr *NMSaddr)
{
(void) NMSaddr;

DPRINTF("Rebooting system...\n");

// Reboot the system
NVIC_SystemReset();

// Should not reach here
return OSAL_FAILURE;
}

osal_basetype_t osal_copy_firmware(uint8_t source_slotid, uint8_t dest_slotid, Csmp_Slothdr *slots) {
uint32_t gecko_btl_dst_slot_id = 0UL;
uint32_t gecko_btl_src_slot_id = 0UL;
static BootloaderStorageSlot_t slotinf = { 0U };
uint32_t dst_length = 0UL;
uint32_t src_length = 0UL;
uint32_t chunk_size = GECKO_BTL_SLOT_CPY_CHUNK_SIZE;
uint8_t *chunk = NULL;
uint32_t offset = 0;

if (slots == NULL) {
DPRINTF("copy_firmware_slot: slot is NULL\n");
return OSAL_FAILURE;
}

if (dest_slotid == source_slotid ||
dest_slotid == RUN_IMAGE ||
dest_slotid == RUN_IMAGE) {
DPRINTF("copy_firmware_slot: src and/or dst slot id is invalid\n");
return OSAL_FAILURE;
}


// copy slot image
gecko_btl_dst_slot_id = __slotid2gblslotid(dest_slotid);
gecko_btl_src_slot_id = __slotid2gblslotid(source_slotid);

if (bootloader_getStorageSlotInfo(gecko_btl_dst_slot_id, &slotinf) != BOOTLOADER_OK) {
DPRINTF("copy_firmware_slot: dest bootloader_getStorageSlotInfo failed\n");
return OSAL_FAILURE;
}
dst_length = slotinf.length;

if (bootloader_getStorageSlotInfo(gecko_btl_src_slot_id, &slotinf) != BOOTLOADER_OK) {
DPRINTF("copy_firmware_slot: src bootloader_getStorageSlotInfo failed\n");
return OSAL_FAILURE;
}

if (dst_length < slotinf.length) {
DPRINTF("copy_firmware_slot: dst slot is smaller than src slot\n");
return OSAL_FAILURE;
}

src_length = slotinf.length;

chunk = osal_malloc(GECKO_BTL_SLOT_CPY_CHUNK_SIZE);
if (chunk == NULL) {
DPRINTF("copy_firmware_slot: malloc failed\n");
return OSAL_FAILURE;
}

DPRINTF("Erasing destination slot...\n");
assert(bootloader_eraseStorageSlot(gecko_btl_dst_slot_id) == BOOTLOADER_OK);
DPRINTF("Copying source slot to destination slot...\n");

while(src_length) {
chunk_size = src_length < GECKO_BTL_SLOT_CPY_CHUNK_SIZE ? src_length : GECKO_BTL_SLOT_CPY_CHUNK_SIZE;

if (bootloader_readStorage(gecko_btl_src_slot_id, offset, chunk, chunk_size) != BOOTLOADER_OK) {
DPRINTF("copy_firmware_slot: bootloader_readStorage failed\n");
osal_free(chunk);
return OSAL_FAILURE;
}

if (bootloader_writeStorage(gecko_btl_dst_slot_id, offset, chunk, chunk_size) != BOOTLOADER_OK) {
DPRINTF("copy_firmware_slot: bootloader_writeStorage failed\n");
osal_free(chunk);
return OSAL_FAILURE;
}

offset += chunk_size;
src_length -= chunk_size;
}

osal_free(chunk);

// copy header
memcpy(&slots[dest_slotid], &slots[source_slotid], sizeof(Csmp_Slothdr));
if (osal_write_slothdr(dest_slotid, &slots[dest_slotid]) != OSAL_SUCCESS) {
DPRINTF("copy_firmware_slot: osal_write_slothdr failed\n");
return OSAL_FAILURE;
}

return OSAL_SUCCESS;
}
6 changes: 6 additions & 0 deletions osal/efr32_wisun/osal_platform_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "sl_memory_manager.h"
#include "sl_sleeptimer.h"
#include "sl_wisun_ntp_timesync_config.h"
#include "../../src/lib/debug.h"

typedef void (*osal_sighandler_t)(int);

Expand All @@ -52,4 +53,9 @@ typedef int osal_sd_set_t;

#define s6_addr address

#define GECKO_BTL_UPLOAD_SLOT_ID 0
#define GECKO_BTL_BACKUP_SLOT_ID 1

#define CSMP_IMAGE_HDR_SIZE 256

#endif
Loading