build: W600-SDK importiert, Firmware-Build und Hello am EVK
Docker-Build mit gcc-arm-none-eabi 4.9-2014q4 (statt Homebrew-Cask) verwendet, Dockerfile/tools/docker.sh dafür aus Task 13 vorgezogen. cmake/sdk.cmake schont gcc 4.9 (kennt -fcommon/-Wno-error=... nicht). Zwei zusätzliche SDK-Stubs (EarlyInit, pre_gpio_config) in src/sys/sdk_stubs.c ergänzt, siehe sdk/PATCHES.md.
This commit is contained in:
@@ -0,0 +1,577 @@
|
||||
/**
|
||||
* @file wm_fls.c
|
||||
*
|
||||
* @brief flash Driver Module
|
||||
*
|
||||
* @author dave
|
||||
*
|
||||
* Copyright (c) 2015 Winner Microelectronics Co., Ltd.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "wm_hostspi.h"
|
||||
#include "wm_flash.h"
|
||||
#include "wm_dbg.h"
|
||||
#include "wm_mem.h"
|
||||
#include "wm_fls_gd25qxx.h"
|
||||
|
||||
|
||||
static struct tls_fls *spi_fls = NULL;
|
||||
|
||||
int tls_spifls_read_id(u32 * id)
|
||||
{
|
||||
u32 cmd;
|
||||
int err;
|
||||
|
||||
cmd = FLS_CMD_READ_DEV_ID;
|
||||
*id = 0;
|
||||
|
||||
err = tls_spi_read_with_cmd((const u8 *) &cmd, 4, (u8 *) id, 3);
|
||||
|
||||
if (err != TLS_SPI_STATUS_OK)
|
||||
{
|
||||
TLS_DBGPRT_ERR("flash read ID fail(%d)!\n", err);
|
||||
return TLS_FLS_STATUS_EIO;
|
||||
}
|
||||
|
||||
TLS_DBGPRT_FLASH_INFO("flash ID - 0x%x.\n", *id);
|
||||
|
||||
return TLS_FLS_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function is used to read data from the flash.
|
||||
*
|
||||
* @param[in] addr is byte offset addr for read from the flash.
|
||||
* @param[in] buf is user for data buffer of flash read
|
||||
* @param[in] len is byte length for read.
|
||||
*
|
||||
* @retval TLS_FLS_STATUS_OK if read sucsess
|
||||
* @retval TLS_FLS_STATUS_EIO if read fail
|
||||
* @retval TLS_FLS_STATUS_EPERM if flash driver module not beed installed
|
||||
* @retval TLS_FLS_STATUS_ENODRV if the current spi flash driver not installed
|
||||
* @retval TLS_FLS_STATUS_EINVAL if parameter error
|
||||
*
|
||||
* @note None
|
||||
*/
|
||||
int tls_spifls_read(u32 addr, u8 * buf, u32 len)
|
||||
{
|
||||
int err;
|
||||
u32 read_bytes;
|
||||
struct tls_fls_drv *drv;
|
||||
|
||||
if (spi_fls == NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
|
||||
return TLS_FLS_STATUS_EPERM;
|
||||
}
|
||||
|
||||
if (spi_fls->current_drv == NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
|
||||
return TLS_FLS_STATUS_ENODRV;
|
||||
}
|
||||
|
||||
if ((addr >= spi_fls->current_drv->total_size) || (len == 0)
|
||||
|| (buf == NULL))
|
||||
{
|
||||
return TLS_FLS_STATUS_EINVAL;
|
||||
}
|
||||
tls_os_sem_acquire(spi_fls->fls_lock, 0);
|
||||
drv = spi_fls->current_drv;
|
||||
read_bytes =
|
||||
((addr + len) > drv->total_size) ? (drv->total_size - addr) : len;
|
||||
|
||||
err = TLS_FLS_STATUS_OK;
|
||||
|
||||
err = drv->read(addr, buf, read_bytes);
|
||||
tls_os_sem_release(spi_fls->fls_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int tls_spifls_fast_read(u32 addr, u8 * buf, u32 len)
|
||||
{
|
||||
int err;
|
||||
u32 read_bytes;
|
||||
struct tls_fls_drv *drv;
|
||||
|
||||
if (spi_fls == NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
|
||||
return TLS_FLS_STATUS_EPERM;
|
||||
}
|
||||
|
||||
if (spi_fls->current_drv == NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
|
||||
return TLS_FLS_STATUS_ENODRV;
|
||||
}
|
||||
|
||||
if ((addr >= spi_fls->current_drv->total_size) || (len == 0)
|
||||
|| (buf == NULL))
|
||||
{
|
||||
return TLS_FLS_STATUS_EINVAL;
|
||||
}
|
||||
if ((spi_fls->current_drv->flags & TLS_FLS_FLAG_FAST_READ) !=
|
||||
TLS_FLS_FLAG_FAST_READ)
|
||||
{
|
||||
return TLS_FLS_STATUS_ENOSUPPORT;
|
||||
}
|
||||
|
||||
drv = spi_fls->current_drv;
|
||||
read_bytes =
|
||||
((addr + len) > drv->total_size) ? (drv->total_size - addr) : len;
|
||||
|
||||
err = TLS_FLS_STATUS_OK;
|
||||
|
||||
err = drv->fast_read(addr, buf, read_bytes);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int tls_spifls_page_write(u32 page, u8 * buf, u32 page_cnt)
|
||||
{
|
||||
int err;
|
||||
u32 write_pages;
|
||||
u32 i;
|
||||
struct tls_fls_drv *drv;
|
||||
|
||||
if (spi_fls == NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
|
||||
return TLS_FLS_STATUS_EPERM;
|
||||
}
|
||||
|
||||
if (spi_fls->current_drv == NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
|
||||
return TLS_FLS_STATUS_ENODRV;
|
||||
}
|
||||
|
||||
if ((page >= (spi_fls->current_drv->total_size / spi_fls->current_drv->page_size))
|
||||
|| (page_cnt == 0) || (buf == NULL))
|
||||
{
|
||||
return TLS_FLS_STATUS_EINVAL;
|
||||
}
|
||||
|
||||
drv = spi_fls->current_drv;
|
||||
write_pages = ((page + page_cnt) > (drv->total_size / drv->page_size)) ?
|
||||
((drv->total_size / drv->page_size) -page) : page_cnt;
|
||||
|
||||
err = TLS_FLS_STATUS_OK;
|
||||
|
||||
for (i = 0; i < write_pages; i++)
|
||||
{
|
||||
err = drv->page_write(page + i, buf + i * drv->page_size);
|
||||
if (err != TLS_FLS_STATUS_OK)
|
||||
{
|
||||
TLS_DBGPRT_ERR("flash page write fail(page %d)!\n", (page + i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function is used to write data to the flash.
|
||||
*
|
||||
* @param[in] addr is byte offset addr for write to the flash
|
||||
* @param[in] buf is the data buffer want to write to flash
|
||||
* @param[in] len is the byte length want to write
|
||||
*
|
||||
* @retval TLS_FLS_STATUS_OK if write flash success
|
||||
* @retval TLS_FLS_STATUS_EPERM if flash struct point is null
|
||||
* @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed
|
||||
* @retval TLS_FLS_STATUS_EINVAL if argument is invalid
|
||||
* @retval TLS_FLS_STATUS_EIO if io error
|
||||
* @retval TLS_FLS_STATUS_ENOMEM if memory allocation fail
|
||||
*
|
||||
* @note None
|
||||
*/
|
||||
int tls_spifls_write(u32 addr, u8 * buf, u32 len)
|
||||
{
|
||||
u8 *cache;
|
||||
int err;
|
||||
u32 sector_addr;
|
||||
u32 sector_off;
|
||||
u32 sector_remain;
|
||||
u32 cntforFF;
|
||||
u32 write_bytes;
|
||||
u32 write_page = 0;
|
||||
u32 i;
|
||||
struct tls_fls_drv *drv;
|
||||
|
||||
if (spi_fls == NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
|
||||
return TLS_FLS_STATUS_EPERM;
|
||||
}
|
||||
|
||||
if (spi_fls->current_drv == NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
|
||||
return TLS_FLS_STATUS_ENODRV;
|
||||
}
|
||||
|
||||
if ((addr >= spi_fls->current_drv->total_size) || (len == 0)
|
||||
|| (buf == NULL))
|
||||
{
|
||||
return TLS_FLS_STATUS_EINVAL;
|
||||
}
|
||||
tls_os_sem_acquire(spi_fls->fls_lock, 0);
|
||||
drv = spi_fls->current_drv;
|
||||
|
||||
err = TLS_FLS_STATUS_OK;
|
||||
|
||||
cache = tls_mem_alloc(drv->sector_size);
|
||||
if (cache == NULL)
|
||||
{
|
||||
tls_os_sem_release(spi_fls->fls_lock);
|
||||
TLS_DBGPRT_ERR("allocate sector cache memory(%dB) fail!\n",
|
||||
drv->sector_size);
|
||||
return TLS_FLS_STATUS_ENOMEM;
|
||||
}
|
||||
|
||||
sector_addr = addr / drv->sector_size; //Section addr
|
||||
sector_off = (addr % drv->sector_size); //Offset in section
|
||||
sector_remain = drv->sector_size - sector_off;
|
||||
write_bytes = len;
|
||||
TLS_DBGPRT_FLASH_INFO("write to flash: sector address - %d, sector off - %x.\n", sector_addr,
|
||||
sector_off);
|
||||
|
||||
if(write_bytes <= sector_remain)
|
||||
{
|
||||
sector_remain = write_bytes; //Not bigger with remain size in section
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
TLS_DBGPRT_FLASH_INFO("firstly, read the sector - %d to cache.\n", sector_addr);
|
||||
err = drv->read(sector_addr * drv->sector_size, cache, drv->sector_size);
|
||||
if (err != TLS_FLS_STATUS_OK)
|
||||
{
|
||||
TLS_DBGPRT_ERR("flash read fail(sector %d)!\n", sector_addr);
|
||||
break;
|
||||
}
|
||||
|
||||
cntforFF = 0;
|
||||
for(i = 0; i < sector_remain; i++)
|
||||
{
|
||||
if(cache[i + sector_off] == 0xFF)
|
||||
{
|
||||
cntforFF++;
|
||||
}
|
||||
cache[i + sector_off] = buf[i];
|
||||
}
|
||||
|
||||
//If the flash address to be written is all 0xFF, then erase sector is not necessary;
|
||||
if( cntforFF != sector_remain)
|
||||
{
|
||||
TLS_DBGPRT_FLASH_INFO("second, erase the sector - %d.\n", sector_addr);
|
||||
err = drv->erase(sector_addr);
|
||||
if (err != TLS_FLS_STATUS_OK)
|
||||
{
|
||||
TLS_DBGPRT_ERR("flash erase fail(sector %d)!\n", sector_addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( (cntforFF != sector_remain ) || ((sector_off == 0) && (sector_remain == drv->sector_size)))
|
||||
{
|
||||
for(i = 0; i < (drv->sector_size / drv->page_size); i++)
|
||||
{
|
||||
err = drv->page_write(sector_addr * drv->sector_size / drv->page_size + i, &cache[i * drv->page_size]);
|
||||
if (err != TLS_FLS_STATUS_OK)
|
||||
{
|
||||
TLS_DBGPRT_ERR("flash page write fail(page %d)!\n", i);
|
||||
tls_mem_free(cache);
|
||||
tls_os_sem_release(spi_fls->fls_lock);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
write_page = (sector_off / drv->page_size) == 15 ? 16 : (sector_off + sector_remain) / drv->page_size + 1;
|
||||
//As long as this sector is not erased in this round, we only program the changed pages instead of all of them.
|
||||
for(i = (sector_off / drv->page_size); i < write_page; i++)
|
||||
{
|
||||
err = drv->page_write(sector_addr * drv->sector_size / drv->page_size + i, &cache[i * drv->page_size]);
|
||||
if (err != TLS_FLS_STATUS_OK)
|
||||
{
|
||||
TLS_DBGPRT_ERR("flash page write fail(page %d)!\n", i);
|
||||
tls_mem_free(cache);
|
||||
tls_os_sem_release(spi_fls->fls_lock);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(write_bytes == sector_remain)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
sector_addr++;
|
||||
sector_off = 0;
|
||||
buf += sector_remain;
|
||||
write_bytes -= sector_remain;
|
||||
if(write_bytes > (drv->sector_size))
|
||||
sector_remain = drv->sector_size;
|
||||
else
|
||||
sector_remain = write_bytes; //Next section will finish
|
||||
}
|
||||
}
|
||||
|
||||
tls_mem_free(cache);
|
||||
tls_os_sem_release(spi_fls->fls_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int tls_spifls_erase(u32 sector)
|
||||
{
|
||||
int err;
|
||||
struct tls_fls_drv *drv;
|
||||
|
||||
if (spi_fls == NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
|
||||
return TLS_FLS_STATUS_EPERM;
|
||||
}
|
||||
|
||||
if (spi_fls->current_drv == NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
|
||||
return TLS_FLS_STATUS_ENODRV;
|
||||
}
|
||||
|
||||
if (sector >= (spi_fls->current_drv->total_size / spi_fls->current_drv->sector_size))
|
||||
{
|
||||
TLS_DBGPRT_ERR("the sector to be erase overflow!\n");
|
||||
return TLS_FLS_STATUS_EINVAL;
|
||||
}
|
||||
tls_os_sem_acquire(spi_fls->fls_lock, 0);
|
||||
drv = spi_fls->current_drv;
|
||||
|
||||
err = TLS_FLS_STATUS_OK;
|
||||
|
||||
err = drv->erase(sector);
|
||||
tls_os_sem_release(spi_fls->fls_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int tls_spifls_chip_erase(void)
|
||||
{
|
||||
int err;
|
||||
struct tls_fls_drv *drv;
|
||||
|
||||
if (spi_fls == NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
|
||||
return TLS_FLS_STATUS_EPERM;
|
||||
}
|
||||
|
||||
if (spi_fls->current_drv == NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
|
||||
return TLS_FLS_STATUS_ENODRV;
|
||||
}
|
||||
|
||||
drv = spi_fls->current_drv;
|
||||
|
||||
err = TLS_FLS_STATUS_OK;
|
||||
|
||||
err = drv->chip_erase();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int tls_spifls_get_param(u8 type, void *param)
|
||||
{
|
||||
int err;
|
||||
struct tls_fls_drv *drv;
|
||||
|
||||
if (spi_fls == NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
|
||||
return TLS_FLS_STATUS_EPERM;
|
||||
}
|
||||
|
||||
if (spi_fls->current_drv == NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
|
||||
return TLS_FLS_STATUS_ENODRV;
|
||||
}
|
||||
|
||||
if (param == NULL)
|
||||
{
|
||||
return TLS_FLS_STATUS_EINVAL;
|
||||
}
|
||||
tls_os_sem_acquire(spi_fls->fls_lock, 0);
|
||||
drv = spi_fls->current_drv;
|
||||
err = TLS_FLS_STATUS_OK;
|
||||
switch (type)
|
||||
{
|
||||
case TLS_FLS_PARAM_TYPE_ID:
|
||||
*((u32 *) param) = drv->id;
|
||||
break;
|
||||
|
||||
case TLS_FLS_PARAM_TYPE_SIZE:
|
||||
*((u32 *) param) = drv->total_size;
|
||||
break;
|
||||
|
||||
case TLS_FLS_PARAM_TYPE_PAGE_SIZE:
|
||||
*((u32 *) param) = drv->page_size;
|
||||
break;
|
||||
|
||||
case TLS_FLS_PARAM_TYPE_PROG_SIZE:
|
||||
*((u32 *) param) = drv->program_size;
|
||||
break;
|
||||
|
||||
case TLS_FLS_PARAM_TYPE_SECTOR_SIZE:
|
||||
*((u32 *) param) = drv->sector_size;
|
||||
break;
|
||||
|
||||
default:
|
||||
TLS_DBGPRT_WARNING("invalid parameter ID!\n");
|
||||
err = TLS_FLS_STATUS_EINVAL;
|
||||
break;
|
||||
}
|
||||
tls_os_sem_release(spi_fls->fls_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int tls_spifls_drv_register(struct tls_fls_drv *fls_drv)
|
||||
{
|
||||
u32 cpu_sr;
|
||||
struct tls_fls_drv *drv;
|
||||
|
||||
if (fls_drv == NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
|
||||
return TLS_FLS_STATUS_EINVAL;
|
||||
}
|
||||
|
||||
dl_list_for_each(drv, &spi_fls->fls_drvs, struct tls_fls_drv, drv_list)
|
||||
{
|
||||
if (drv->id == fls_drv->id)
|
||||
{
|
||||
TLS_DBGPRT_WARNING
|
||||
("corresponding spi flash driver has registered!\n");
|
||||
return TLS_FLS_STATUS_EEXIST;
|
||||
}
|
||||
}
|
||||
|
||||
cpu_sr = tls_os_set_critical();
|
||||
dl_list_add_tail((struct dl_list *) &spi_fls->fls_drvs,
|
||||
(struct dl_list *) &fls_drv->drv_list);
|
||||
tls_os_release_critical(cpu_sr);
|
||||
|
||||
TLS_DBGPRT_FLASH_INFO("the spi flash driver is registered successfully!\n");
|
||||
|
||||
return TLS_FLS_STATUS_OK;
|
||||
}
|
||||
|
||||
int tls_spifls_drv_unregister(struct tls_fls_drv *fls_drv)
|
||||
{
|
||||
TLS_DBGPRT_WARNING
|
||||
("unregister spi flash driver operation is not supported!\n");
|
||||
return TLS_FLS_STATUS_EPERM;
|
||||
}
|
||||
|
||||
int tls_spifls_probe(void)
|
||||
{
|
||||
int err;
|
||||
u32 id;
|
||||
struct tls_fls_drv *drv;
|
||||
|
||||
if (spi_fls == NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
|
||||
return TLS_FLS_STATUS_EPERM;
|
||||
}
|
||||
if (spi_fls->current_drv != NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("the current spi flash has fount the matched driver!\n");
|
||||
return TLS_FLS_STATUS_EBUSY;
|
||||
}
|
||||
|
||||
TLS_DBGPRT_FLASH_INFO("try to read the current spi flash ID.\n");
|
||||
err = tls_spifls_read_id(&id);
|
||||
if (err != TLS_FLS_STATUS_OK)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
|
||||
TLS_DBGPRT_FLASH_INFO("current spi flash ID - 0x%x.\n", id);
|
||||
|
||||
dl_list_for_each(drv, &spi_fls->fls_drvs, struct tls_fls_drv, drv_list)
|
||||
{
|
||||
err = drv->probe(id);
|
||||
if (err != TLS_FLS_STATUS_OK)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
|
||||
tls_spi_setup(drv->mode, drv->cs_active, drv->clock);
|
||||
|
||||
TLS_DBGPRT_FLASH_INFO("matched the spi flash driver.\n");
|
||||
spi_fls->current_drv = drv;
|
||||
break;
|
||||
}
|
||||
|
||||
if (spi_fls->current_drv == NULL)
|
||||
{
|
||||
TLS_DBGPRT_WARNING("not found the matched spi flash driver!\n");
|
||||
return TLS_FLS_STATUS_ENODRV;
|
||||
}
|
||||
|
||||
return TLS_FLS_STATUS_OK;
|
||||
}
|
||||
|
||||
int tls_spifls_init(void)
|
||||
{
|
||||
struct tls_fls *fls;
|
||||
int err;
|
||||
|
||||
if (spi_fls != NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("flash driver module has been installed!\n");
|
||||
return TLS_FLS_STATUS_EBUSY;
|
||||
}
|
||||
|
||||
fls = (struct tls_fls *) tls_mem_alloc(sizeof(struct tls_fls));
|
||||
if (fls == NULL)
|
||||
{
|
||||
TLS_DBGPRT_ERR("allocate @spi_fls fail!\n");
|
||||
return TLS_FLS_STATUS_ENOMEM;
|
||||
}
|
||||
|
||||
memset(fls, 0, sizeof(*fls));
|
||||
dl_list_init((struct dl_list *) &fls->fls_drvs);
|
||||
err = tls_os_sem_create(&fls->fls_lock, 1);
|
||||
if (err != TLS_OS_SUCCESS)
|
||||
{
|
||||
tls_mem_free(fls);
|
||||
TLS_DBGPRT_ERR("create semaphore @fls_lock fail!\n");
|
||||
return TLS_FLS_STATUS_ENOMEM;
|
||||
}
|
||||
spi_fls = fls;
|
||||
|
||||
tls_spifls_drv_install();
|
||||
|
||||
return TLS_FLS_STATUS_OK;
|
||||
}
|
||||
|
||||
int tls_spifls_exit(void)
|
||||
{
|
||||
TLS_DBGPRT_FLASH_INFO("Not support flash driver module uninstalled!\n");
|
||||
return TLS_FLS_STATUS_EPERM;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user