3.1.7.5 Wi-Fi OTA Service Interface

The OTA service role is to enable the module firmware update over the network link. The OTA service has the HTTP based file download and RNWF Device Firmware Update (DFU) implementation. The OTA service open ups a TCP tunnel to receive the OTA server and firmware image details. Any device (say PC or Mobile) in the network can initiate the firmware download process. Once the OTA service receives all the necessary details, it starts downloading the firmware image and reports each downloaded chunk to user application over the callback. The user application needs to store the firmware in the local memory. After the successful download the user application can use the OTA service API's to flash new image into the RNWF module. The OTA service API call syntax is provided below:
RNWF_RESULT_t RNWF_OTA_SrvCtrl( RNWF_OTA_SERVICE_t request, void *input)
The following table provides the list of OTA services available:
Table 3-10. OTA Services
Option/CommandInputDescription
RNWF_OTA_ENABLEBuffer of 4096 (to align with DFU max write size) bytesEnable OTA service and opens a TCP tunnel to receive the OTA server and Image details
RNWF_OTA_SET_CALLBACKCallback handler Register callback function for the OTA service to report the status
RNWF_OTA_DFU_INITNoneGenerates the DFU pattern and places the RNWF module in firmware update mode
RNWF_OTA_DFU_WRITEchunk_addr, chunk_size, chunk_ptrWrites the given chunk into the RNWF module. Max chunk size can be 4096 bytes.
RNWF_OTA_DFU_ERASEchunk_addr, chunk_size, chunk_ptrErases the provided size of memory (chunk_ptr can be NULL)
RNWF_OTA_DISABLENoneNot used in V1.0.0 release
RNWF_OTA_REQUESTStructure containing details of image to be downloadedRequest OTA Service to setup a connection with OTA server to start image download
RNWF_OTA_SET_SRVC_CALLBACKCallback handlerRegister callback function from any service using OTA Service
RNWF_OTA_AUTO_MODENoneNot used in V1.0.0 release
RNWF_OTA_RESETNoneRequest reset of RNWF11
The following table captures the OTA Callback event codes and event data:
Table 3-11. OTA Event Codes
EventResponse ComponentDescription
RNWF_EVENT_DWLD_STARTTotal size of the image file to be downloadedGiven image file download has started
RNWF_EVENT_DWLD_DONETotal size of downloaded Image fileFirmware download process completed, the application can initialize the DFU and start flle
RNWF_EVENT_FILE_CHUNKchunk_addr, chunk_size, chunk_ptrReceived image file chunk, the received data chunk must be saved in non-volatile memory
RNWF_EVENT_DWLD_FAILNoneFirmware download failed
RNWF_EVENT_MAKE_UARTNone Not used in V1.0.0 release
RNWF_EVENT_CONFIG_INFONone Not used in V1.0.0 release
RNWF_EVENT_IMAGE_INFO Structure containing detailed information about Image like File Name, Image Type etcEvent used to notify customer application about image details

The sequence chart for the OTA process is provided below:

Figure 3-22. OTA Process

The example code for OTA DFU is provided below:

/*
    OTA application
*/
extern uint8_t app_buf[OTA_BUF_LEN_MAX];
uint32_t gOta_file_size = 0;
void APP_OTA_Program(uint32_t flash_addr, uint32_t flash_size)
{   
    RNWF_OTA_CHUNK_t ota_chunk = { .chunk_addr = 0x60000000, .chunk_ptr = app_buf, .chunk_size = flash_size}; 
    printf("Triggering DFU %lu\r\n", flash_size);
    RNWF_OTA_SrvCtrl(RNWF_OTA_DFU_INIT, (void *)NULL);            
    while(RNWF_OTA_SrvCtrl(RNWF_OTA_DFU_ERASE, (void *)&ota_chunk) != RNWF_PASS);
    while(flash_size)
    {                
        ota_chunk.chunk_size = (flash_size < OTA_BUF_LEN_MAX)?flash_size:OTA_BUF_LEN_MAX; 
        /* User needs to read the stored OTA image and pass-in to RNWF_OTA_SrvCtrl() */                
        HighSpeed_Read_Cont(flash_addr, ota_chunk.chunk_size, (char *)app_buf);                            
        RNWF_OTA_SrvCtrl(RNWF_OTA_DFU_WRITE, (void *)&ota_chunk);
        flash_size -= ota_chunk.chunk_size;
        ota_chunk.chunk_addr += ota_chunk.chunk_size;
        flash_addr += ota_chunk.chunk_size;
        printf("Remaining %lu bytes\r\n", flash_size);  
    }
}
void APP_OTA_Callback(RNWF_OTA_EVENT_t event, void *p_str)
{
    static uint32_t flash_addr = OTA_FLASH_IMAGE_START;
    switch(event)
    {
        case RNWF_EVENT_MAKE_UART:
            break;
        case RNWF_EVENT_DWLD_START:
        {
            printf("Total Size = %lu\r\n", *(uint32_t *)p_str); 
            printf("Erasing the SPI Flash\r\n");
            WREN();
            Chip_Erase();
            Wait_Busy();
            SPI_Global_Block_Protection_Unlock();
            printf("Erasing Complete!\r\n"); 
        }
        break;
        case RNWF_EVENT_DWLD_DONE:
        {                                                 
            printf("Download Success!= %lu bytes\r\n", *(uint32_t *)p_str);
            /* Completed the Image download, start the DFU */ 
            APP_OTA_Program(OTA_FLASH_IMAGE_START, *(uint32_t *)p_str);            
            APP_SW_RESET_Handler();
        }
        break;        
        case RNWF_EVENT_FILE_CHUNK:
        {
            volatile RNWF_OTA_CHUNK_t *ota_chunk = (RNWF_OTA_CHUNK_t *)p_str;  
            /* Save the received Image chunk into the serial SST flash*/             
            Sector_Program(flash_addr, ota_chunk->chunk_ptr, ota_chunk->chunk_size);            
            flash_addr += ota_chunk->chunk_size;
        }    
        break;
        case RNWF_EVENT_DWLD_FAIL:
        {
            /* Erase the Serial SST flash*/
            WREN();
            Chip_Erase();
            Wait_Busy();            
        }
        break;
        default:
            break;
    }
}
void APP_WIFI_Callback(RNWF_WIFI_EVENT_t event, uint8_t *p_str)
{
    switch(event)
    {
        case RNWF_DHCP_DONE:
        {
            printf("DHCP IP:%s\n", &p_str[2]); 
            // Enable OTA by passing the OTA buffer space
            if(RNWF_OTA_SrvCtrl(RNWF_OTA_ENABLE, (void *)app_buf) == RNWF_PASS)
            {
                printf("Successfully Enabled the OTA\r\n");
            }
            else
            {
                printf("Failed to enable the OTA\r\n");
            }
            break;       
        }
        default:
        {
            break;
        }
    }
}
void RNWF_APP_Initialize(void)
{    
    /* Wi-Fii Connectivity */
    RNWF_WIFI_PARAM_t wifi_sta_cfg = {RNWF_WIFI_MODE_STA, HOME_AP_SSID, HOME_AP_PASSPHRASE, HOME_AP_SECURITY, 1};    
    printf("Connecting to %s\r\n", HOME_AP_SSID);
    RNWF_WIFI_SrvCtrl(RNWF_WIFI_SET_CALLBACK, APP_WIFI_Callback);
    RNWF_WIFI_SrvCtrl(RNWF_SET_WIFI_PARAMS, &wifi_sta_cfg);

    /* RNWF Application Callback register */
    RNWF_OTA_SrvCtrl(RNWF_OTA_SET_CALLBACK, (void *)APP_OTA_Callback);
    while(1)
    {  
        RNWF_EVENT_Handler();
    }    
}