0% found this document useful (0 votes)
106 views13 pages

Flash Bloques

This document contains code for functions that control an SPI flash memory chip. It defines constants for SPI flash commands, structures for flash info and sectors. Functions are provided to initialize the SPI driver, read/write/erase sectors, check for ready status, and lock/unlock memory blocks. Mutex locking is used for read/write access.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
106 views13 pages

Flash Bloques

This document contains code for functions that control an SPI flash memory chip. It defines constants for SPI flash commands, structures for flash info and sectors. Functions are provided to initialize the SPI driver, read/write/erase sectors, check for ready status, and lock/unlock memory blocks. Mutex locking is used for read/write access.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 13

/**

******************************************************************************
* @file
stm32f4xx_spi.c
* @author VC
* @version V1.2.0
* @date
13-April-2015
* @brief This file provides the kernel rtc functions
******************************************************************************
* Use the following configuration settings in the middleware component
* to connect to this driver.
*
* Configuration Setting
Value
* ------------------------* Connect to hardware via Driver_Flash# = n (default: 0)
*
******************************************************************************
*/
#include "drv_sflash.h"
#include "drv_SPI.h"
#include <string.h>
#include "sst26vfx.h"
#include "drv_led.h"
#define EVENT_RTOS
#ifdef EVENT_RTOS
#include "cmsis_os.h"
#endif
/* User Configuration */
#define DRIVER_SPI

DRIVER_SPI2

/* SPI Data Flash definitions */


#define BUS_SPEED
#define SFLASH_TIMEOUT_STOP

33000000
/* Bus speed
((uint32_t)1000) /* 1s */

/* SPI Data Flash Commands */


#define CMD_READ_DATA
#define CMD_READ_DATA_HS
#define CMD_READ_STATUS

0x03 // 40MHz
0x0B // 104MHz
0x05

#define CMD_PAGE_PROGRAM
#define CMD_WRITE_ENABLE
#define CMD_WRITE_DISABLE

0x02
0x06
0x04

#define CMD_ERASE_BLOCK
#define CMD_ERASE_SECTOR
#define CMD_ERASE_CHIP

0xD8
0x20
0xC7

#define CMD_READ_ID
#define CMD_RESET_ENABLE
#define CMD_RESET

0x9F
0x66
0x99

#define CMD_WR_BLOCK_PROTECTION 0x42


#define CMD_RD_BLOCK_PROTECTION 0x72

*/

#define
#define
#define
#define

FLAG_ADDR_PRESENT
FLAG_TYPE_READ
FLAG_TYPE_WRITE
FLAG_TYPE_ONLY_CMD

(1<<0)
(1<<1)
(1<<2)
(1<<3)

/* Locking memory array */


#define
BIT_BLOCK_SECTOR_0 (64)
#define
BIT_BLOCK_SECTOR_1 (66)
/* READ AND WRITE MUTEX */
osMutexDef(mut_sflash);
osMutexId mut_sflash_id;
static const uint8_t lock_Structure[] ={
BIT_BLOCK_SECTOR_0,
BIT_BLOCK_SECTOR_1
};
/* SPI Driver */
#define ptrSPI

(&DRIVER_SPI)

/* SST26VFx Sector Information */


#ifdef SFLASH_SECTORS_DEFINE
static SFLASH_SECTOR SFLASH_SECTOR_TABLE[] = {
SFLASH_SECTORS_DEFINE
};
#define SFLASH_SECTOR_TABLE_COUNT
(sizeof(SFLASH_SECTOR_TABLE)/sizeof
(SFLASH_SECTOR))
#else
#define SFLASH_SECTOR_TABLE
NULL
#define SFLASH_SECTOR_TABLE_COUNT
0
#endif
/* Revisar */
typedef struct {
uint8_t
uint8_t

state;
block_protection[10];

uint16_t
uint32_t
uint8_t

sector_size;
nsector;
nsector_mem[SFLASH_SECTOR_SIZE];

}sflashInfo_str;
sflashInfo_str SflashInfo;
/* Flash Information */
//static SFLASH_INFO FlashInfo = {
// SFLASH_SECTOR_INFO,
// SFLASH_SECTOR_COUNT,
// SFLASH_SECTOR_SIZE,
//
SFLASH_PAGE_COUNT,
// SFLASH_PAGE_SIZE,
// SFLASH_PROGRAM_UNIT,
// SFLASH_ERASED_VALUE
//};

static SFLASH_INFO FlashInfo;


static SFLASH_STATUS sst26vfx_ReadID(uint16_t *id_code);
typedef struct{
uint8_t cmd;
uint8_t dummy;
uint8_t flag;
}sflash_Command_str;

// command byte
// cont dummy bytes
// read/write & present addr

const sflash_Command_str sst26vf_command[]


{CMD_RESET
{CMD_RESET_ENABLE
{CMD_WRITE_ENABLE
{CMD_WRITE_DISABLE
{CMD_READ_DATA
ENT},
{CMD_READ_DATA_HS
ENT},
{CMD_READ_STATUS
{CMD_READ_ID
{CMD_RD_BLOCK_PROTECTION
{CMD_WR_BLOCK_PROTECTION
{CMD_PAGE_PROGRAM
SENT},
{CMD_ERASE_SECTOR
SENT},
{CMD_ERASE_BLOCK
SENT},
{CMD_ERASE_CHIP
};

= {
,0
,0
,0
,0
,0

,
,
,
,
,

FLAG_TYPE_ONLY_CMD},
FLAG_TYPE_ONLY_CMD},
FLAG_TYPE_ONLY_CMD},
FLAG_TYPE_ONLY_CMD},
FLAG_TYPE_READ | FLAG_ADDR_PRES

,1 , FLAG_TYPE_READ | FLAG_ADDR_PRES
,0
,0
,0
,0
,0

,
,
,
,
,

FLAG_TYPE_READ},
FLAG_TYPE_READ},
FLAG_TYPE_READ},
FLAG_TYPE_WRITE},
FLAG_TYPE_WRITE | FLAG_ADDR_PRE

,0 , FLAG_TYPE_WRITE | FLAG_ADDR_PRE
,0 , FLAG_TYPE_WRITE | FLAG_ADDR_PRE
,0 , FLAG_TYPE_ONLY_CMD}

#define COMMAND_DEF_SIZE (sizeof(sst26vf_command)/sizeof(sflash_Command_str))


/**
\fn
SFLASH_STATUS Send_Command(cmd, addr, *data, cnt)
\brief
Send an existing command on the table.
\return
\ref execution_status
*/
static SFLASH_STATUS Send_Command(uint8_t cmd, uint32_t addr, uint8_t *data, uin
t32_t cnt){
uint8_t cmd_str[4+3];
uint8_t n = 0;
sflash_Command_str const *command;
for(uint8_t i = 0; i< COMMAND_DEF_SIZE ; i++){
if(sst26vf_command[i].cmd == cmd){
//check param
command = &sst26vf_command[i];
break;
}
}
// check param
if(command == NULL || ((command->flag & FLAG_TYPE_READ) && (data == NULL ||
cnt == 0)))
return SFLASH_ERROR;

/* Select Slave */
ptrSPI->ActiveNSS();
cmd_str[n++] = command->cmd;
if (command->flag & FLAG_ADDR_PRESENT ){
cmd_str[n++] = (uint8_t)(addr >> 16);
cmd_str[n++] = (uint8_t)(addr >> 8);
cmd_str[n++] = (uint8_t)(addr >> 0);
}
/* Add dummy bytes */
n += command->dummy;
/* Send cmd + [addr] + [dummy] */
if (ptrSPI->Send(cmd_str, n) != SPI_STATE_OK){
goto transfer_error;
}
while (ptrSPI->GetState() == SPI_STATE_BUSY){}
if(command->flag & FLAG_TYPE_WRITE){
/* Send data n-byte */
if (ptrSPI->Send(data, cnt) != SPI_STATE_OK){
goto transfer_error;
}
while (ptrSPI->GetState() == SPI_STATE_BUSY){}
}
else if(command->flag & FLAG_TYPE_READ){
/* Recv data n-bytes */
if (ptrSPI->Receive(data, cnt) != SPI_STATE_OK) {
goto transfer_error;
}
while (ptrSPI->GetState() == SPI_STATE_BUSY){}
}
/* Deselect Slave */
ptrSPI->InactiveNSS();
return SFLASH_OK;
transfer_error:
/* Deselect Slave */
ptrSPI->InactiveNSS();
return SFLASH_ERROR;
}
/**
\fn
SFLASH_STATUS Write_Enable (void)
\brief
Enable write complete Flash.
\return
\ref execution_status
*/
static SFLASH_STATUS Write_Enable(void){
return Send_Command(CMD_WRITE_ENABLE,0,NULL,0);

}
/**
\fn
SFLASH_STATUS Write_Disable (void)
\brief
Disable write complete Flash.
\return
\ref execution_status
*/
//static SFLASH_STATUS Write_Disable(void){
//
//
return Send_Command(CMD_WRITE_DISABLE,0,NULL,0);
//}
/**
\fn
\brief

SFLASH_STATUS Write_Enable (void)


Enable write complete Flash.
Optional function for faster full chip erase.
\ref execution_status

\return
*/
static SFLASH_STATUS Reset(void){

if( Send_Command(CMD_RESET_ENABLE,0,NULL,0) != SFLASH_OK)


return SFLASH_ERROR;
return Send_Command(CMD_RESET,0,NULL,0);
}
/**
\fn
\brief

SFLASH_STATUS Write_Enable (void)


Enable write complete Flash.
Optional function for faster full chip erase.
\ref execution_status

\return
*/
static SFLASH_STATUS Read_Block_Protection(void){

return Send_Command(CMD_RD_BLOCK_PROTECTION,0,SflashInfo.block_protection,10
);
}
/**
\fn
\brief

SFLASH_STATUS Write_Enable (void)


Enable write complete Flash.
Optional function for faster full chip erase.
\ref execution_status

\return
*/
//static unsigned char SimmetryBytes[] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0
x01};
static SFLASH_STATUS Write_Block_Protection(void){
//
);

memset(SflashInfo.block_protection, 0, sizeof(SflashInfo.block_protection)

//
for (int i = 0; i< sizeof(lock_Structure);i++) {
//
SflashInfo.block_protection[(9-lock_Structure[i]/8)] |= SimmetryBytes
[lock_Structure[i] % 8];
//
}
//memset(SflashInfo.block_protection, 0, sizeof(SflashInfo.block_protection)
);

Write_Enable();
return Send_Command(CMD_WR_BLOCK_PROTECTION,0,SflashInfo.block_protection,10
);
}
static SFLASH_STATUS Unlock_Block_Protection(void) {
sflashInfo_str temp_fInfo;
memset(temp_fInfo.block_protection, 0, sizeof(temp_fInfo.block_protection));
Write_Enable();
return Send_Command(CMD_WR_BLOCK_PROTECTION,0,temp_fInfo.block_protection,10
);
}

static SFLASH_STATUS Read_Status_Register (uint8_t *status){


return Send_Command(CMD_READ_STATUS,0,status,1);
}
static SFLASH_STATUS Wait_Ready (void){
uint8_t status;
uint32_t tickstart;
/* Get tick */
tickstart = HAL_GetTick();
while((HAL_GetTick() - tickstart ) < SFLASH_TIMEOUT_STOP)
{
if(Read_Status_Register(&status) == SFLASH_OK && !(status & 0x80))
{
return SFLASH_OK;
}
}
return SFLASH_ERROR;
}
static SFLASH_STATUS Protected_Blocks_Init(void) {
for (int i = 0; i< sizeof(lock_Structure);i++) {
SflashInfo.block_protection[lock_Structure[i]/8] |= lock_Structure[i] %
8;
}
return SFLASH_OK;
}
/**

\fn
\brief
\param[in]
\return

int32_t at45dbx_Initialize (ARM_Flash_SignalEvent_t cb_event)


Initialize the Flash Interface.
cb_event Pointer to \ref ARM_Flash_SignalEvent
\ref execution_status

*/
uint16_t code;
const SPI_ParamConfig_str SPI_Config = {
.mode
= SPI_CMODE_MASTER,
.fomat
= SPI_CPOL1_CPHA1,
.data_bits= SPI_DATA_BIT_8BIT,
.order
= SPI_MSB_LSB,
.speed
= BUS_SPEED
};
static SFLASH_STATUS sst26vfx_Initialize (ARM_Flash_SignalEvent_t cb_event) {
/* SPI Init */
ptrSPI->Initialize();
/* check serial flash*/
Reset();
Read_Block_Protection();
Protected_Blocks_Init();
if (sst26vfx_ReadID(&code) == SFLASH_ERROR)
return SFLASH_ERROR;
FlashInfo.sector_info = SFLASH_SECTOR_TABLE;
SflashInfo.nsector = SFLASH_MAX_ADDRESS + 1; //fuera de rango
Write_Block_Protection();
#ifdef EVENT_RTOS
mut_sflash_id = osMutexCreate(osMutex(mut_sflash));
#endif
return SFLASH_OK;
}
/**
\fn
int32_t ARM_Flash_Uninitialize (void)
\brief
De-initialize the Flash Interface.
\return
\ref execution_status
*/
static SFLASH_STATUS sst26vfx_Uninitialize (void) {

if( Send_Command(CMD_RESET_ENABLE,0,NULL,0) != SFLASH_OK)


return SFLASH_ERROR;
return Send_Command(CMD_RESET,0,NULL,0);
}
/**
\fn
int32_t ARM_Flash_EraseSector (uint32_t addr)

\brief
\param[in]
\return

Erase Flash Sector.


addr Sector address
\ref execution_status

*/
static SFLASH_STATUS sst26vfx_EraseSector (uint32_t addr) {
SFLASH_STATUS ret;
/* Init sector */
SflashInfo.nsector = SFLASH_MAX_ADDRESS + 1;
/* Check Status */
Wait_Ready();
Write_Enable();
ret = Send_Command(CMD_ERASE_SECTOR, addr, NULL, 0);
return ret;
}
/**
\fn
int32_t ARM_Flash_EraseBlock (uint32_t addr)
\brief
Erase Flash Block.
\param[in] addr Sector address
\return
\ref execution_status
*/
static SFLASH_STATUS sst26vfx_EraseBlock (uint32_t addr) {
/* Init sector */
SflashInfo.nsector = SFLASH_MAX_ADDRESS + 1;
/* Check Status */
Wait_Ready();
Write_Enable();
/* Borra el bloque (no los sectores asociados al bloque) */
return Send_Command(CMD_ERASE_BLOCK, addr, NULL, 0);
}
/**
\fn
t)
\brief
\param[in]
\param[out]
\param[in]
\return
*/
static int32_t

int32_t sst26vfx_ReadData (uint32_t addr, void *data, uint32_t cn


Read data from Flash.
addr Data address.
data Pointer to a buffer storing the data read from Flash.
cnt Number of data items to read.
number of data items read or \ref execution_status
sst26vfx_ReadData (uint32_t addr, void *data, uint32_t cnt) {

int i;
#ifdef EVENT_RTOS
osMutexWait(mut_sflash_id,osWaitForever);
#endif
/* check parameters 4Mbytes */
if( (addr + cnt) > SFLASH_MAX_ADDRESS || data == NULL){
#ifdef EVENT_RTOS
osMutexRelease(mut_sflash_id);

#endif
return ARM_DRIVER_ERROR_PARAMETER;
}

for (i=0;i<cnt/256;i++) {
/* Check Status */
Wait_Ready();
if (Send_Command(CMD_READ_DATA, addr, (uint8_t *)data + 256*i, 256) == S
FLASH_OK){
continue;
}
else {
#ifdef EVENT_RTOS
osMutexRelease(mut_sflash_id);
#endif
return SFLASH_ERROR;
}
}
for (int j=0;j<cnt%256;j++) {
/* Check Status */
Wait_Ready();
if (Send_Command(CMD_READ_DATA, addr, (uint8_t *)data + 256*i +j, cnt%25
6) == SFLASH_OK){
continue;
}
else {
#ifdef EVENT_RTOS
osMutexRelease(mut_sflash_id);
#endif
return SFLASH_ERROR;
}
}
#ifdef EVENT_RTOS
osMutexRelease(mut_sflash_id);
#endif
return cnt;
}
/**
\fn
int32_t cnt)
\brief
\param[in]
\param[in]
Flash.
\param[in]
\return
*/

int32_t ARM_Flash_ProgramData (uint32_t addr, const void *data, u


Program data to Flash.
addr Data address.
data Pointer to a buffer containing the data to be programmed to
cnt Number of data items to program.
number of data items programmed or \ref execution_status

#define SECTOR_SUBADDRESS(addr)
#define SECTOR_ADDRESS(addr)

(addr & (SFLASH_SECTOR_SIZE-1))


(addr & ~(SFLASH_SECTOR_SIZE-1))

/* check COUNT_DAT <= PAGE_PROGRAM_DATA(256)*/


uint8_t Sector_CheckAndCopyData(uint32_t addr, uint8_t *data, uint32_t cnt, uint

16_t inc){
uint8_t result = 0;
uint32_t sector = ( addr & ~(SFLASH_SECTOR_SIZE-1));
uint32_t sub_addr = addr & (SFLASH_SECTOR_SIZE-1);
if(SflashInfo.nsector != sector){
// leemos el sector entero
sst26vfx_ReadData(sector, SflashInfo.nsector_mem, SFLASH_SECTOR_SIZE);
SflashInfo.nsector = sector;
}
for(uint32_t i=0; i< cnt; i++){
/* chech AND data, if (RAM &FLASH) != RAM -> erase Sector */
if((SflashInfo.nsector_mem[sub_addr+i] & *(data+(i*inc))) != *(data+
(i*inc)))
result = 1;
/* copy data in RAM */
SflashInfo.nsector_mem[sub_addr+i] = *(data+(i*inc));
}
return result;
}
static SFLASH_STATUS Sector_ProgramData(uint32_t addr, const void *data, uint32_
t cnt){
const uint8_t *buf;
uint32_t n;
SFLASH_STATUS result = SFLASH_OK;
buf = data;
while(cnt && result == SFLASH_OK)
{
n = SFLASH_PAGE_SIZE - (addr % SFLASH_PAGE_SIZE);
if (n > cnt) n = cnt;
/* Check Status */
Wait_Ready();
Write_Enable();
/* Send Command with Address */
result = Send_Command(CMD_PAGE_PROGRAM, addr, (void *)buf, n);
Wait_Ready();
/* Calculate next page to program */
addr += n;
buf += n;
cnt -= n;
}
return result;
}
static int32_t _ProgramData (uint32_t addr, const void *data, uint32_t cnt, uint
16_t inc) {

const uint8_t *buf;


uint32_t nbytes;
SFLASH_STATUS result = SFLASH_OK;

/* checking del dato */


buf = data;
while(cnt && result == SFLASH_OK){
nbytes = SFLASH_SECTOR_SIZE - SECTOR_SUBADDRESS(addr);
if (nbytes > cnt) {
nbytes = cnt;
}
if(Sector_CheckAndCopyData(addr, (uint8_t *)buf, nbytes, inc) == 1) {
sst26vfx_EraseSector(SECTOR_ADDRESS(addr));
/* Optimizar con indices reales - ahora graba el sector completo */
result = Sector_ProgramData(SECTOR_ADDRESS(addr), (uint8_t *)SflashI
nfo.nsector_mem, SFLASH_SECTOR_SIZE);
}
else{
/* Program datos de interes*/
result = Sector_ProgramData(addr, (uint8_t *)buf, nbytes);
}
addr += nbytes;
buf += nbytes;
cnt -= nbytes;
}
if(result == SFLASH_OK) {
return cnt;
}

return SFLASH_ERROR;
}
static int32_t sst26vfx_ProgramData (uint32_t addr, const void *data, uint32_t c
nt) {
uint32_t ret;
int i;
/* Program data with increment 1 */
#ifdef EVENT_RTOS
osMutexWait(mut_sflash_id,osWaitForever);
#endif
for (i = 0;i<(cnt/256);i++) {
ret = _ProgramData(addr, (uint8_t *)data+256*i, 256, 1);
}
for (int j = 0;j < (cnt%256);j++) {
ret += _ProgramData(addr, (uint8_t *)data+256*i+j, cnt%256, 1);
}

#ifdef EVENT_RTOS
osMutexRelease(mut_sflash_id);
#endif
return ret;
}
static int32_t sst26vfx_FillData (uint32_t addr, const uint8_t data, uint32_t cn
t) {
/* Program Data with increment 0 */
return _ProgramData(addr, &data, cnt, 0);
}
/**
\fn
int32_t ARM_Flash_EraseSector (uint32_t addr)
\brief
Erase Flash Sector.
\param[in] addr Sector address
\return
\ref execution_status
*/
static SFLASH_STATUS sst26vfx_ErasePage (uint32_t addr) {
return SFLASH_ERROR_UNSUPPORTED;
}
/**
\fn
SFLASH_STATUS sst26vfx_ReadID (void)
\brief
Read ID chip.
\return
\ref execution_status
*/
static SFLASH_STATUS sst26vfx_ReadID(uint16_t *id_code){
uint8_t bufout[3];
if (Send_Command(CMD_READ_ID, 0, bufout, 3) == SFLASH_OK){
*id_code = *((uint16_t *)&bufout[1]);
return SFLASH_OK;
}
return SFLASH_ERROR;
}
/**
\fn
\brief

int32_t ARM_Flash_EraseChip (void)


Erase complete Flash.
Optional function for faster full chip erase.
\ref execution_status

\return
*/
static SFLASH_STATUS sst26vfx_EraseChip (void) {
/* Init sector */
SflashInfo.nsector = SFLASH_MAX_ADDRESS + 1;
/* Check Status */
Wait_Ready();
Write_Enable();

return Send_Command(CMD_ERASE_CHIP, 0, NULL, 0);


}

/**
\fn
ARM_FLASH_STATUS ARM_Flash_GetStatus (void)
\brief
Get Flash status.
\return
Flash status \ref ARM_FLASH_STATUS
*/
static SFLASH_STATUS sst26vfx_GetStatus (void) {
return SFLASH_OK;
}
/**
\fn
ARM_FLASH_INFO * ARM_Flash_GetInfo (void)
\brief
Get Flash information.
\return
Pointer to Flash information \ref ARM_FLASH_INFO
*/
SFLASH_INFO * sst26vfx_GetInfo (void) {
return &FlashInfo;
}
/**
\fn
ARM_DRIVER_VERSION ARM_Flash_GetVersion (void)
\brief
Get driver version.
\return
\ref ARM_DRIVER_VERSION
*/
static uint16_t sst26vfx_GetVersion (void) {
return SFLASH_DRIVER_VERSION(1,0);
//DriverVersion;
}
/* Flash Driver Control Block */
SFLASH_DRIVER driver_sst26vfx = {
sst26vfx_GetVersion,
sst26vfx_Initialize,
sst26vfx_Uninitialize,
sst26vfx_ReadData,
sst26vfx_ProgramData,
sst26vfx_FillData,
sst26vfx_ErasePage,
sst26vfx_EraseSector,
sst26vfx_EraseBlock,
sst26vfx_EraseChip,
sst26vfx_GetStatus,
sst26vfx_ReadID,
sst26vfx_GetInfo,
Write_Block_Protection,
Unlock_Block_Protection,
};

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy