Цитата(Sergiocars @ Mar 17 2014, 21:41)

Выложите пожалуйста функцию записи в память!!!
n25q128 массово применяется не в одном серийном устройстве.
Я бы советовал для начала обратится к ней используя софтовый spi.
Приведённый ниже код взят из серийного проекта.
В оригинале используется аппаратный spi, но процессор не STM, поэтому я привёл программный (ранее использовавшийся и также 100% рабочий).
Надёюсь поможет Вам разобраться в проблеме.
CODE
//-------------------------------------------
unsigned char SPIWriteChar(unsigned char cmd)
{
unsigned char i;
unsigned char recv;
recv = 0;
for(i=0; i<8; i++)
{
if((cmd&0x80) != 0)
{
SPI_PORT_SET = MOSI;
}
else
{
SPI_PORT_CLR = MOSI;
}
SPI_PORT_SET = SCK;
recv<<=1;
if((SPI_PIN & MISO) != 0)
{
recv|=0x01;
}
SPI_PORT_CLR = SCK;
cmd<<=1;
}
return recv;
}
//-------------------------------------------
//-------------------------------------------
unsigned char SPIReadChar(void)
{
return SPIWriteChar(0x00);
}
//-------------------------------------------
//-------------------------------------------
//макросы доступа к устройствам SPI
void DESELECT_SPI(void)
{
//деактивируем все устройства SPI
SPI_PORT_SET = nSS_SFLASH;
SPI_PORT_CLR = SCK|MOSI; //устанавливаем выводы в исходное состояние
}
//-------------------------------------------
//-------------------------------------------
void SELECT_SPI(unsigned int msk)
{
DESELECT_SPI(); //деактивируем все устройства SPI
SPI_PORT_CLR = msk; //активируем необходимое
}
//-------------------------------------------
//-------------------------------------------
//инициализация SPI
void ConfigureSPI()
{
//настройка порта и начальных уровней
SPI_DIR &= ~MISO;
SPI_DIR |= SCK|MOSI;
SPI_DIR |= nSS_SFLASH;
SPI_PORT_SET = nSS_SFLASH;
SPI_PORT_CLR = SCK|MOSI;
}
//-------------------------------------------
CODE
//--------------------------------
//------------------------------------
//коды команд работы с памятью
enum {
N25_WREN = 0x06, //write enable
N25_WRDI = 0x04, //write disable
N25_RDID = 0x9f, //read id
N25_RDSR = 0x05, //read status register
N25_WRSR = 0x01, //write status reg
N25_WRLR = 0xe5, //write lock reg
N25_RDLR = 0xe8, //red lock reg
N25_READ = 0x03, //read data bytes
N25_FAST_READ = 0x0b, //fast read data bytes
N25_PP = 0x02, //page prog
N25_SE = 0xd8, //sector erase 64k
N25_SE_4K = 0x20, //sub sector erase 4k
N25_BE = 0xc7, //bulk erase
};
//------------------------------------
//------------------------------------
//биты регистра статуса
enum {
N25_WIP = 0x01, //write in progress
N25_WIL = 0x02, //write enable latch status
N25_BP2 = 0x04, //
N25_BP1 = 0x08, //
N25_BP0 = 0x10, //
N25_SRWD = 0x80, //status register write disable
};
//------------------------------------
//------------------------------------
//параметры памяти
enum {
//N25_SECTOR_NUM = 4096, //sectors by 4k
N25_SECTOR_NUM = 2048, //sectors by 4k
N25_SECTOR_SIZE = 4096,
N25_PAGE_SIZE = 256,
M25_PAGE_PER_SECTOR = N25_SECTOR_SIZE/N25_PAGE_SIZE, //4096/256=16
N25_PP_TM = 10, //таймаут записи страницы
N25_SE_4K_TM = 1000, //таймаут стирания сектора
};
//------------------------------------
//процедура разрешения записи в память
void n25setWREN(void)
{
SELECT_SPI(nSS_SFLASH); //выбираем устройство spi
SPIWriteChar(N25_WREN); //запись кода команды
DESELECT_SPI(); //отпускаем устройство spi
}
//--------------------------------
//--------------------------------
//процедура запрещения записи в память
void n25setWRDIS(void)
{
SELECT_SPI(nSS_SFLASH); //выбираем устройство spi
SPIWriteChar(N25_WRDI); //запись кода команды
DESELECT_SPI(); //отпускаем устройство spi
}
//--------------------------------
//--------------------------------
//ожидание завершения операции записи
unsigned int n25waitBusy(unsigned int tm)
{
volatile unsigned int status;
SELECT_SPI(nSS_SFLASH); //выбираем устройство spi
SPIWriteChar(N25_RDSR); //запись кода команды
for(unsigned int i=0; i<tm; i++)
{
status = SPIWriteChar(0x00); //читаем статус
if((status & N25_WIP) == 0)
{
DESELECT_SPI(); //отпускаем устройство spi
return 1; //оперция завершена
}
//ожидание паузы в 1 mS
//for(volatile unsigned int j=0; j<(50*1000); j++); //пауза на исполнение
delay_ms(1);
}
DESELECT_SPI(); //отпускаем устройство spi
return 0; //ошибка таймаута
}
//--------------------------------
//--------------------------------
//процедура чтения страницы памяти
void n25pageRead(unsigned char* buff, unsigned int page, unsigned int byte, unsigned int size)
{
unsigned int addr=0;
//вычисляем физический адрес байта
addr = page*N25_PAGE_SIZE+byte;
SELECT_SPI(nSS_SFLASH); //выбираем устройство spi
SPIWriteChar(N25_READ); //запись кода команды
SPIWriteChar( (unsigned char) (addr>>16) ); //запись адреса
SPIWriteChar( (unsigned char) (addr>>8) ); //запись адреса
SPIWriteChar( (unsigned char) (addr>>0) ); //запись адреса
while(size--)
{
*buff++ = SPIWriteChar(0x00);
}
DESELECT_SPI(); //отпускаем устройство spi
}
//-----------------------------
//--------------------------------
//процедура чтения сектора памяти
void n25sectorRead(unsigned char* buff, unsigned int sector, unsigned int byte, unsigned int size)
{
unsigned int addr=0;
//вычисляем физический адрес байта
addr = sector*N25_SECTOR_SIZE+byte;
SELECT_SPI(nSS_SFLASH); //выбираем устройство spi
SPIWriteChar(N25_READ); //запись кода команды
SPIWriteChar( (unsigned char) (addr>>16) ); //запись адреса
SPIWriteChar( (unsigned char) (addr>>8) ); //запись адреса
SPIWriteChar( (unsigned char) (addr>>0) ); //запись адреса
while(size--)
{
*buff++ = SPIWriteChar(0x00);
}
DESELECT_SPI(); //отпускаем устройство spi
}
//-----------------------------
//--------------------------------
//процедура записи страницы памяти
void n25pageWrite(unsigned char* buff, unsigned int page, unsigned int byte, unsigned int size)
{
unsigned int addr=0;
//вычисляем физический адрес байта
addr = page*N25_PAGE_SIZE+byte;
n25setWREN(); //разрешаем запись в память
SELECT_SPI(nSS_SFLASH); //выбираем устройство spi
SPIWriteChar(N25_PP); //запись кода команды
SPIWriteChar( (unsigned char) (addr>>16) ); //запись адреса
SPIWriteChar( (unsigned char) (addr>>8) ); //запись адреса
SPIWriteChar( (unsigned char) (addr>>0) ); //запись адреса
//записываем данные
while(size--)
{
SPIWriteChar(*buff++);
}
DESELECT_SPI(); //отпускаем устройство spi
//ожидаем завершения операции
n25waitBusy(N25_PP_TM);
}
//-----------------------------
//--------------------------------
//процедура записи сектора памяти
void n25sectorWrite(unsigned char* buff, unsigned int sector, unsigned int size)
{
unsigned int page;
unsigned int page_num;
//вычисляем кол-во страниц и стартовый адрес страницы
page = sector*M25_PAGE_PER_SECTOR;
page_num = size/N25_PAGE_SIZE;
for(unsigned int i=0; i<page_num; i++)
{
n25pageWrite(buff+i*N25_PAGE_SIZE, page+i, 0, N25_PAGE_SIZE);
}
}
//-----------------------------
//--------------------------------
//процедура стирания сектора
void n25sectorErase(unsigned int sector)
{
//вычисляем физический адре байта
unsigned int addr = sector*N25_SECTOR_SIZE;
n25setWREN(); //разрешаем запись в память
SELECT_SPI(nSS_SFLASH); //выбираем устройство spi
SPIWriteChar(N25_SE_4K); //запись кода команды
SPIWriteChar( (unsigned char) (addr>>16) ); //запись адреса
SPIWriteChar( (unsigned char) (addr>>8) ); //запись адреса
SPIWriteChar( (unsigned char) (addr>>0) ); //запись адреса
DESELECT_SPI(); //отпускаем устройство spi
//ожидаем завершения операции
n25waitBusy(N25_SE_4K_TM);
n25setWRDIS();
}
//--------------------------------
//-----------------------------
//инициализация памяти
void n25xxInit(void)
{
n25setWRDIS();
}
//-----------------------------