Teste semf
Kontakt

SpiNorFlash

General

The purpose of this module is to facilitate executing main operations like write, read and erase on an external flash memory device that has an spi communication interface.
The base class NorSpiFlash is written in a way, that the device classes for serveral chips can do easily.

Device Declaration and Definition

Declare and define a class that inherits from SpiNorFlash class and redefine some of its functions. The main goal of this class is to connect the interface of the semf library with the external flash memory that uses a spi communication interface. In the following example we consider an EON EN25F80 flash memory.

#include "Components/Storage/Flash/spinorflash.h" 

class EonEn25f80 : public semf::SpiNorFlash 
{ 
public:
	using SpiNorFlash::SpiNorFlash; 
	size_t sector(uint32_t address) const; 
	uint32_t address(size_t sector) const; 
	size_t sectorSize(size_t sector) const; 
	void unlockAllSectors(); 

private: 
	void setAddress(uint32_t globalAddress); 
	void setAddress(size_t sectorNo, size_t pageNo); 
	uint8_t addressByteLength() const; 
	size_t pageSize() const;
}; 

// please have a look into the datasheet to know the exact number of sectors. 
size_t EonEn25f80::sector(uint32_t address) const 
{ 
	return static_cast(address / ( 4 * 1024)); 
} 

uint32_t EonEn25f80::address(size_t sector) const
{ 
	return static_cast(sector * 4 * 1024); 
} 

size_t EonEn25f80::sectorSize(size_t sector) const 
{ 
	return 4 * 1024; 
} 

void EonEn25f80::unlockAllSectors() 
{ 
	return setStatusRegister(0x00); 
	// please have a look into the datasheet how to unlock all sectors. 
} 

void EonEn25f80::setAddress(uint32_t globalAddress) 
{ 
	intBuffer()[0] = static_cast(globalAddress >> 16 & 0x0F); 
	// insertion of the most significant 4 bits. 
	intBuffer()[1] = static_cast(globalAddress >> 8 & 0xFF); 
	// insertion of the next 8 bits. 
	intBuffer()[2] = static_cast(globalAddress & 0xFF); 
	// insertion of the least significant 8 bits. 
} 

// The sector and the page have to be disassembled. Please have a look into the datasheet to know the memory organization. 
void EonEn25f80::setAddress(size_t sector, size_t page) 
{ 
	// Divide the sector index by 16 (block index, a hex digit between 0 and F). 
	intBuffer()[0] = static_cast(sector >> 4); 
	// Sector index inside the block (a hex digit between 0 and F). 
	intBuffer()[1] = static_cast((sector) % 16)) << 4; // The last three hex digits are dedicated for the page number. intBuffer()[1] = static_cast((page & 0x0FFF) >> 8) | intBuffer[1]; 
	intBuffer[2] = (page & 0x00FF); 
} 

uint8_t EonEn25f80::addressByteLength() const 
{ 
	return 3; 
} 

size_t EonEn25f80::pageSize() const 
{ 
	return 256; 
}

Initialization

The first step for setting up the external flash memory SpiNorFlash object is to initialize an spi hardware module and configure a gpio pin as an output for chip select (usually done in hardware configuration, for example for STM by Stm32CubeMX). The second step is creating an SpiMaster object referencing the Spi handler. Thirdly, create a Gpio object referencing the hardware port and pin for the chip select pin. SpiMaster and Gpio objects are then passed to the SpiFlash object (by registerInterface()).

In this example we consider STM32F4 microcontroller, and EN25F80 external flash memory.

In this example, we consider pin 13 GPIO_PIN_13 of port b GPIOB for the chip select pin, which has to be set as an output in hardware configuration.

#include "main.h"
#include "Devices/Storage/NorFlash/eonen25f80.h" 
#include "HardwareAbstraction/Stm32/stm32f4spimaster.h"
#include "HardwareAbstraction/Stm32/stm32f4gpio.h"

// Hardware handler which is defined in 'main.c' file.
extern SPI_HandleTypeDef hspi; 

semf::Stm32F4Gpio spiCs(GPIOB, GPIO_PIN_13);
semf::Stm32F4SpiMaster spimaster(hspi);  
semf::EonEn25f80 extFlash(spimaster, spiCs);
extFlash.unlockAllSectors();

Usage

In this example, the flash memory is erased firstly using erase function, then 10 bytes are written to sector 0 using write function, lastly these bytes are read after that using read.

Signal/slot mechanism is used. So, the slot functions has to be declared and defined.

Signals has to be cleared/disconnected from other slots before utilization.

extFlash.erased.connect(&onExternalMemoryErased); 
extFlash.erased.clear();

// slot, which is invoked by 'erased'-signal from external flash memory. 
void onExternalMemoryErased() 
{ 
	// do something
} 

uint8_t dataToBeWritten[10] = {0,1,2,3,4,5,6,7,8,9}; 
uint32_t flashMemoryAddress = extFlash.address(0); 
extFlash.write(flashMemoryAddress, dataToBeWritten, 10); 

// slot, which is invoked by 'dataWritten'-signal from external flash memory. 
void onExternalMemoryDataWritten() 
{ 
	// do something
} 

uint8_t dataToBeRead[10] = {0}; 
uint32_t flashMemoryAddress = extFlash.address(0); 
extFlash.read(flashMemoryAddress, dataToBeRead, 10);

// slot, which is invoked by 'dataAvailable'-signal from external flash memory. 
void onExternalMemoryDataRead() 
{ 
	// do something 
}

zurück zur Dokumentation