178 lines
5.5 KiB
C
178 lines
5.5 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the
|
|
* distribution.
|
|
*
|
|
* Neither the name of Texas Instruments Incorporated nor the names of
|
|
* its contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
******************************************************************************/
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include "flashloader.h"
|
|
#include "flash.h"
|
|
|
|
/* Array holding erased state of the flash sectors. */
|
|
static bool g_is_erased[FLASH_MAX_SECTOR_COUNT];
|
|
|
|
extern uint8_t g_retain_buf[];
|
|
|
|
uint32_t flashloader_init(struct flash_params *params, uint8_t *buf1,
|
|
uint8_t *buf2)
|
|
{
|
|
/* Initialize params buffers */
|
|
memset((void *)params, 0, 2 * sizeof(struct flash_params));
|
|
params[0].buf_addr = (uint32_t)buf1;
|
|
params[1].buf_addr = (uint32_t)buf2;
|
|
|
|
/* Mark all sectors at "not erased" */
|
|
memset(g_is_erased, false, sizeof(g_is_erased));
|
|
|
|
return STATUS_OK;
|
|
}
|
|
|
|
uint32_t flashloader_erase_and_program(uint8_t *src, uint32_t address,
|
|
uint32_t byte_count)
|
|
{
|
|
if (byte_count > BUFFER_LEN)
|
|
return STATUS_FAILED_INVALID_ARGUMENTS;
|
|
|
|
/* Erase affected sectors */
|
|
uint32_t status = flashloader_erase_sectors(address, byte_count);
|
|
|
|
if (status != STATUS_OK)
|
|
return status;
|
|
|
|
/* Program data */
|
|
status = flashloader_program(src, address, byte_count);
|
|
|
|
return status;
|
|
}
|
|
|
|
uint32_t flashloader_program_with_retain(uint8_t *src, uint32_t address,
|
|
uint32_t byte_count)
|
|
{
|
|
#if (BUFFER_LEN > FLASH_ERASE_SIZE)
|
|
#error Buffer size cannot be larger than the flash sector size!
|
|
#endif
|
|
|
|
uint32_t first_sector_idx;
|
|
uint32_t last_sector_idx;
|
|
uint32_t status = STATUS_OK;
|
|
uint32_t i;
|
|
|
|
first_sector_idx = flashloader_address_to_sector(address);
|
|
last_sector_idx = flashloader_address_to_sector(address + byte_count - 1);
|
|
|
|
/* Mark all sectors as "not erased" before starting */
|
|
memset(g_is_erased, false, sizeof(g_is_erased));
|
|
|
|
uint32_t sec_offset = address % FLASH_ERASE_SIZE;
|
|
uint32_t curr_count;
|
|
uint32_t src_offset = 0;
|
|
|
|
for (i = first_sector_idx; i <= last_sector_idx; i++) {
|
|
|
|
/* Chop off at sector boundary if data goes into the next sector. */
|
|
curr_count = byte_count;
|
|
if ((address + byte_count) > ((i+1) * FLASH_ERASE_SIZE))
|
|
curr_count -= (address + byte_count) % FLASH_ERASE_SIZE;
|
|
|
|
/* Copy flash sector to retain buffer */
|
|
memcpy(g_retain_buf, (void *)(i * FLASH_ERASE_SIZE), FLASH_ERASE_SIZE);
|
|
|
|
/* Copy data buffer to retain buffer */
|
|
memcpy(&g_retain_buf[sec_offset], &src[src_offset], curr_count);
|
|
|
|
/* Erase and program from retain buffer */
|
|
status = flashloader_erase_and_program(g_retain_buf,
|
|
(i * FLASH_ERASE_SIZE), FLASH_ERASE_SIZE);
|
|
if (status != STATUS_OK)
|
|
return status;
|
|
|
|
address += curr_count;
|
|
sec_offset = address % FLASH_ERASE_SIZE;
|
|
byte_count -= curr_count;
|
|
src_offset += curr_count;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
uint32_t flashloader_erase_all(void)
|
|
{
|
|
if (flash_bank_erase(true) != FAPI_STATUS_SUCCESS)
|
|
return STATUS_FAILED_ERASE_ALL;
|
|
|
|
memset(g_is_erased, true, sizeof(g_is_erased));
|
|
|
|
return STATUS_OK;
|
|
}
|
|
|
|
uint32_t flashloader_erase_sectors(uint32_t address, uint32_t byte_count)
|
|
{
|
|
uint32_t first_sector_idx;
|
|
uint32_t last_sector_idx;
|
|
uint32_t status;
|
|
uint32_t idx;
|
|
|
|
/* Floor address to the start of the sector and convert to sector number */
|
|
first_sector_idx = flashloader_address_to_sector(address);
|
|
last_sector_idx = flashloader_address_to_sector(address + byte_count - 1);
|
|
|
|
/* Erase given sector(s) */
|
|
for (idx = first_sector_idx; idx <= last_sector_idx; idx++) {
|
|
|
|
/* Only erase sectors that haven't already been erased */
|
|
if (g_is_erased[idx] == false) {
|
|
status = flash_sector_erase(idx * FLASH_ERASE_SIZE);
|
|
if (status != FAPI_STATUS_SUCCESS) {
|
|
status = (STATUS_FAILED_SECTOR_ERASE |
|
|
((idx << STATUS_EXT_INFO_S) & STATUS_EXT_INFO_M) |
|
|
((status << STATUS_ROM_CODE_S) & STATUS_ROM_CODE_M));
|
|
return status;
|
|
}
|
|
g_is_erased[idx] = true;
|
|
}
|
|
}
|
|
|
|
return STATUS_OK;
|
|
}
|
|
|
|
uint32_t flashloader_program(uint8_t *src, uint32_t address,
|
|
uint32_t byte_count)
|
|
{
|
|
uint32_t status = flash_program(src, address, byte_count);
|
|
if (status != FAPI_STATUS_SUCCESS) {
|
|
status = (STATUS_FAILED_PROGRAM |
|
|
((status << STATUS_ROM_CODE_S) & STATUS_ROM_CODE_M));
|
|
}
|
|
|
|
return STATUS_OK;
|
|
}
|