2019-12-16 06:10:59 +00:00
|
|
|
/****************************************************************************
|
|
|
|
*
|
|
|
|
* Copyright 2019 Samsung Electronics All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing,
|
|
|
|
* software distributed under the License is distributed on an
|
|
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
|
|
|
* either express or implied. See the License for the specific
|
|
|
|
* language governing permissions and limitations under the License.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Included Files
|
|
|
|
****************************************************************************/
|
|
|
|
#include "mbed.h"
|
|
|
|
#include "shmem_save.h"
|
|
|
|
#include "modem_io_device.h"
|
|
|
|
#include "s5js100_pwr.h"
|
|
|
|
#include "sflash_api.h"
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Pre-processor Definitions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#define FLASH_CS_BASE_OLD 0x40EAA000
|
|
|
|
#define FLASH_NV_BASE_OLD 0x40E47000
|
|
|
|
#define FLASH_CAL_BASE_OLD 0x40E87000
|
|
|
|
|
|
|
|
#define FLASH_CS_BASE 0x4059B000
|
|
|
|
#define FLASH_NV_BASE 0x4055B000
|
|
|
|
#define FLASH_CAL_BASE 0x4001B000
|
|
|
|
|
|
|
|
#define FLASH_CS_SIZE (1024 * 300)
|
|
|
|
#define FLASH_NV_SIZE (1024 * 256)
|
|
|
|
#define FLASH_CAL_SIZE (1024 * 128)
|
|
|
|
|
|
|
|
#define REQ_CS_MSG 0x0000A20B
|
|
|
|
#define REQ_NV_MSG 0x0000A21B
|
|
|
|
#define REQ_CAL_MSG 0x0000A22B
|
|
|
|
|
|
|
|
#define BUFFER_SIZE 256
|
|
|
|
#define SFLASH_SECTOR_SIZE 256
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Types
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Global Variables
|
|
|
|
****************************************************************************/
|
|
|
|
static ModemIoDevice *shmem_mio;
|
|
|
|
static unsigned int cur_save_target;
|
|
|
|
static unsigned char *save_cached;
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Data
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Public Data
|
|
|
|
****************************************************************************/
|
|
|
|
extern int nbsleep_req;
|
|
|
|
unsigned int g_flash_cs_base;
|
|
|
|
unsigned int g_flash_nv_base;
|
|
|
|
unsigned int g_flash_cal_base;
|
|
|
|
|
|
|
|
unsigned int g_flash_cs_size = FLASH_CS_SIZE;
|
|
|
|
unsigned int g_flash_nv_size = FLASH_NV_SIZE;
|
|
|
|
unsigned int g_flash_cal_size = FLASH_CAL_SIZE;
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#define SHMEM_SECTION_MAGIC (0x06313184)
|
|
|
|
typedef struct {
|
|
|
|
unsigned int magic0;
|
|
|
|
unsigned int version;
|
|
|
|
unsigned int start;
|
|
|
|
unsigned int magic1;
|
|
|
|
} shmem_section_data;
|
|
|
|
|
|
|
|
static shmem_section_data next_shmem_section[3] = {
|
|
|
|
{SHMEM_SECTION_MAGIC, 1, g_flash_cs_base + (48 * 1024), SHMEM_SECTION_MAGIC},
|
|
|
|
{SHMEM_SECTION_MAGIC, 1, g_flash_nv_base + (48 * 1024), SHMEM_SECTION_MAGIC},
|
|
|
|
{SHMEM_SECTION_MAGIC, 1, g_flash_cal_base + (48 * 1024), SHMEM_SECTION_MAGIC},
|
|
|
|
};
|
|
|
|
|
|
|
|
static shmem_section_data *find_section_data(unsigned int start, unsigned int size)
|
|
|
|
{
|
|
|
|
unsigned int a, max;
|
|
|
|
shmem_section_data *d, *m;
|
|
|
|
|
|
|
|
max = 0;
|
|
|
|
m = NULL;
|
|
|
|
for (a = start; a < start + size; a += 0x1000) {
|
|
|
|
d = (shmem_section_data *)(a + 0x1000 - sizeof(shmem_section_data));
|
|
|
|
if (d->magic0 != 0x06313184 || d->magic1 != 0x06313184) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d->version > max) {
|
|
|
|
max = d->version;
|
|
|
|
m = d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern uint32_t s5js100_sflash_read_capacity(void);
|
|
|
|
|
|
|
|
void shmem_get_data(unsigned int *cs, unsigned int *nv, unsigned int *cal)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
unsigned int start;
|
|
|
|
unsigned int size;
|
|
|
|
} section[3];
|
|
|
|
unsigned int i;
|
|
|
|
shmem_section_data *m;
|
|
|
|
unsigned int ret[3] = {0, 0, 0};
|
|
|
|
//unsigned int FLASH16MB = 0, oldstart, oldsize;
|
|
|
|
//unsigned int psize, poffset;
|
|
|
|
//unsigned char *tmpbuf;
|
|
|
|
//shmem_section_data *tmpsection;
|
|
|
|
|
|
|
|
//initialize SHMEM section depending on FLASH capacity
|
|
|
|
if (s5js100_sflash_read_capacity() == 16 * 1024 * 1024) {
|
|
|
|
g_flash_cs_base = FLASH_CS_BASE_OLD;
|
|
|
|
g_flash_nv_base = FLASH_NV_BASE_OLD;
|
|
|
|
g_flash_cal_base = FLASH_CAL_BASE_OLD;
|
|
|
|
} else if (s5js100_sflash_read_capacity() == 8 * 1024 * 1024) {
|
|
|
|
g_flash_cs_base = FLASH_CS_BASE;
|
|
|
|
g_flash_nv_base = FLASH_NV_BASE;
|
|
|
|
g_flash_cal_base = FLASH_CAL_BASE;
|
|
|
|
} else {
|
2020-01-10 16:58:54 +00:00
|
|
|
mbed_error_printf("no support FLASH size..\n");
|
2019-12-16 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
section[0].start = g_flash_cs_base;
|
|
|
|
section[1].start = g_flash_nv_base;
|
|
|
|
section[2].start = g_flash_cal_base;
|
|
|
|
|
|
|
|
section[0].size = g_flash_cs_size;
|
|
|
|
section[1].size = g_flash_nv_size;
|
|
|
|
section[2].size = g_flash_cal_size;
|
|
|
|
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
m = find_section_data(section[i].start, section[i].size);
|
|
|
|
|
|
|
|
if (m == NULL) {
|
|
|
|
ret[i] = section[i].start;
|
|
|
|
next_shmem_section[i].start = section[i].start + (48 * 1024);
|
|
|
|
} else {
|
|
|
|
ret[i] = m->start;
|
|
|
|
next_shmem_section[i].start = (unsigned int)m + sizeof(shmem_section_data);
|
|
|
|
next_shmem_section[i].version = m->version + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*cs = ret[0];
|
|
|
|
*nv = ret[1];
|
|
|
|
*cal = ret[2];
|
|
|
|
}
|
|
|
|
|
|
|
|
int shmem_data_save(unsigned int msg, uint8_t *buffer, uint16_t real_len, uint32_t t_size, uint32_t s_size)
|
|
|
|
{
|
|
|
|
unsigned int flash_start_addr;
|
|
|
|
unsigned int offset;
|
|
|
|
unsigned int poffset;
|
|
|
|
unsigned int psize;
|
|
|
|
unsigned char *buf;
|
|
|
|
unsigned int cached_size;
|
|
|
|
unsigned int wlen;
|
|
|
|
unsigned int wsize;
|
|
|
|
unsigned int section_idx;
|
|
|
|
|
|
|
|
switch (msg) {
|
|
|
|
case REQ_CS_MSG:
|
|
|
|
section_idx = 0;
|
|
|
|
if (next_shmem_section[0].start + t_size + sizeof(shmem_section_data) < g_flash_cs_base + FLASH_CS_SIZE) {
|
|
|
|
flash_start_addr = next_shmem_section[0].start;
|
|
|
|
} else {
|
|
|
|
flash_start_addr = g_flash_cs_base;
|
|
|
|
}
|
|
|
|
next_shmem_section[0].start = flash_start_addr;
|
|
|
|
break;
|
|
|
|
case REQ_NV_MSG:
|
|
|
|
section_idx = 1;
|
|
|
|
if (next_shmem_section[1].start + t_size + sizeof(shmem_section_data) < g_flash_nv_base + FLASH_NV_SIZE) {
|
|
|
|
flash_start_addr = next_shmem_section[1].start;
|
|
|
|
} else {
|
|
|
|
flash_start_addr = g_flash_nv_base;
|
|
|
|
}
|
|
|
|
next_shmem_section[1].start = flash_start_addr;
|
|
|
|
break;
|
|
|
|
case REQ_CAL_MSG:
|
|
|
|
section_idx = 2;
|
|
|
|
if (next_shmem_section[2].start + t_size + sizeof(shmem_section_data) < g_flash_cal_base + FLASH_CAL_SIZE) {
|
|
|
|
flash_start_addr = next_shmem_section[2].start;
|
|
|
|
} else {
|
|
|
|
flash_start_addr = g_flash_cal_base;
|
|
|
|
}
|
|
|
|
next_shmem_section[2].start = flash_start_addr;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
psize = up_progmem_blocksize();
|
|
|
|
offset = s_size;
|
|
|
|
cached_size = s_size & (psize - 1);
|
|
|
|
wlen = 0;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
wsize = (real_len - wlen + cached_size > psize) ? psize - cached_size : real_len - wlen;
|
|
|
|
|
|
|
|
if (wsize != psize) {
|
|
|
|
memcpy(save_cached + cached_size, buffer + wlen, wsize);
|
|
|
|
buf = save_cached;
|
|
|
|
} else {
|
|
|
|
buf = buffer + wlen;
|
|
|
|
}
|
|
|
|
cached_size += wsize;
|
|
|
|
wlen += wsize;
|
|
|
|
poffset = (offset / psize) * psize;
|
|
|
|
offset += wsize;
|
|
|
|
|
|
|
|
if (cached_size != psize) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
cached_size = 0;
|
|
|
|
sflash_erase(flash_start_addr + poffset);
|
|
|
|
sflash_write(flash_start_addr + poffset, buf, psize);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (real_len + s_size >= t_size) {
|
|
|
|
poffset = (offset / psize) * psize;
|
|
|
|
if (cached_size + sizeof(shmem_section_data) <= psize) {
|
|
|
|
memcpy(save_cached + 0xFF0, (unsigned char *)(&(next_shmem_section[section_idx])), 0x10);
|
|
|
|
sflash_erase(flash_start_addr + poffset);
|
|
|
|
sflash_write(flash_start_addr + poffset, save_cached, psize);
|
|
|
|
} else {
|
|
|
|
sflash_erase(flash_start_addr + poffset);
|
|
|
|
sflash_write(flash_start_addr + poffset, save_cached, cached_size);
|
|
|
|
memcpy(save_cached + 0xFF0, (unsigned char *)(&(next_shmem_section[section_idx])), 0x10);
|
|
|
|
sflash_erase(flash_start_addr + poffset + psize);
|
|
|
|
sflash_write(flash_start_addr + poffset, save_cached, psize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void shmem_factory_reset(void)
|
|
|
|
{
|
|
|
|
unsigned int flash_start_addr;
|
|
|
|
unsigned int poffset = 0;
|
|
|
|
/* erase NV */
|
|
|
|
flash_start_addr = g_flash_nv_base;
|
|
|
|
for (poffset = 0; poffset < 64; poffset++) {
|
|
|
|
sflash_erase(flash_start_addr + poffset * 4096);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* erase CS */
|
|
|
|
flash_start_addr = g_flash_cs_base;
|
|
|
|
for (poffset = 0; poffset < 75; poffset++) {
|
|
|
|
sflash_erase(flash_start_addr + poffset * 4096);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void shmem_save_read_cb(mio_buf *buf, void *data);
|
|
|
|
void shmem_initiate_cb(mio_buf *buf, void *data)
|
|
|
|
{
|
|
|
|
save_cached = (unsigned char *)malloc(4096);
|
|
|
|
|
|
|
|
shmem_mio->register_ReadCb(shmem_save_read_cb, NULL);
|
|
|
|
shmem_mio->write((char *)(&cur_save_target), 4);
|
|
|
|
free_mio_buf(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
void shmem_save_read_cb(mio_buf *buf, void *data)
|
|
|
|
{
|
|
|
|
uint16_t msg_len;
|
|
|
|
uint32_t remain_len, real_len;
|
|
|
|
uint8_t *buffer = (uint8_t *)(buf->data);
|
|
|
|
uint32_t total_size, sent_size;
|
|
|
|
unsigned long long nbsleep_sec;
|
|
|
|
|
|
|
|
msg_len = *(uint16_t *)(buffer + 2);
|
|
|
|
|
|
|
|
if (msg_len != 0) {
|
|
|
|
real_len = msg_len - 8;
|
|
|
|
total_size = *(uint32_t *)(buffer + 4);
|
|
|
|
sent_size = *(uint32_t *)(buffer + 8);
|
|
|
|
remain_len = *(uint32_t *)(buffer + 4) - *(uint32_t *)(buffer + 8);
|
|
|
|
|
|
|
|
shmem_data_save(cur_save_target, buffer + 12, real_len, total_size, sent_size);
|
|
|
|
} else {
|
|
|
|
remain_len = 0;
|
|
|
|
real_len = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
free_mio_buf(buf);
|
|
|
|
|
|
|
|
if (remain_len == real_len) {
|
|
|
|
if (cur_save_target == REQ_CAL_MSG) {
|
|
|
|
free(save_cached);
|
|
|
|
cur_save_target = REQ_CS_MSG;
|
|
|
|
shmem_mio->register_ReadCb(shmem_initiate_cb, NULL);
|
|
|
|
nbsleep_req = 1;
|
|
|
|
nbsleep_sec = ((((unsigned long long)(getreg32(0x81000000 + 0xE4))) << 32) + getreg32(0x81000000 + 0xE8)) / 32768;
|
|
|
|
}
|
|
|
|
|
|
|
|
cur_save_target += 0x10;
|
|
|
|
if (cur_save_target > REQ_CAL_MSG) {
|
|
|
|
cur_save_target = REQ_CS_MSG;
|
|
|
|
shmem_mio->register_ReadCb(shmem_initiate_cb, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
shmem_mio->write((char *)(&cur_save_target), 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
void shmem_save_init(void)
|
|
|
|
{
|
|
|
|
char mio_name[32] = "shmem_save";
|
|
|
|
|
|
|
|
cur_save_target = REQ_CS_MSG;
|
|
|
|
shmem_mio = getModemIoDeviceByName(mio_name);
|
|
|
|
shmem_mio->register_ReadCb(shmem_initiate_cb, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void shmem_save_stop(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|