Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Проблема с памятью MT29F16G08
Форум разработчиков электроники ELECTRONIX.ru > Аналоговая и цифровая техника, прикладная электроника > Цифровые схемы, высокоскоростные ЦС
Akscan
Пытаюсь запустить связку из этой памяти и микроконтроллера AT91RM9200. Инициализация пройдена успешно, id микросхемы я тоже считываю. Также работает считывание страницы. Проблема возникает, когда я пытаюсь записать в память значения. Алгоритм записи следующий:
-Имеется буфер unsigned char dataToWrite[31] для записи, первые два байта которого содержат захардкоренные значения 0xAA и 0xBB
-Следующие индексы неполностью заполнены данными, байт 20. Незаполненные поля обнулены
-Стираю блок, на кототрый я хочу записать данные
-Записываю данные
-Проверяю статус операции, что она успешна
-Читаю данные

Проблема в том, что данные читаются не полностью. Считывается заголовок из 0xAA и 0xBB, 2 нулевых байта, и четыре байта с данными. Весь остальной считанный массив заполнен значениями 0xFF

Кто-нибудь сталкивался с подобным?

Плата работает на частоте 18,43 MHz
MegaVolt
Цитата(Akscan @ Nov 9 2016, 10:00) *
-Имеется буфер unsigned char dataToWrite[31]
Проблема в том, что данные читаются не полностью. Считывается заголовок из 0xAA и 0xBB, 2 нулевых байта, и четыре байта с данными. Весь остальной считанный массив заполнен значениями 0xFF
Как сейчас указана длинна массива? И действительно ли она передаётся равной 32(31)? Или там почему то сейчас передаётся 8?
Akscan
Цитата(MegaVolt @ Nov 9 2016, 10:47) *
Как сейчас указана длинна массива? И действительно ли она передаётся равной 32(31)? Или там почему то сейчас передаётся 8?

Массив передается весь, с данными, и нулями, размером 31
MegaVolt
Цитата(Akscan @ Nov 9 2016, 10:56) *
Массив передается весь, с данными, и нулями, размером 31
Тогда странно. Ибо 0xFF говорит про то что в эти места скорее всего записи не было. И там лежат значения после стирания.

Попробуйте эксперимент: передать массив любых чисел кроме нулевых. Т.е. чтобы ни в данных ни в хвосте не было нулей. И напишите что получиться.
Akscan
Может быть проблема в тактовой частоте? Я прокурил даташит на память, но не нашел(или не заметил) упоминаний о частоте, на которой работает память. Контроллер может слишком быстро писать туда данные?

Цитата(MegaVolt @ Nov 9 2016, 11:04) *
Тогда странно. Ибо 0xFF говорит про то что в эти места скорее всего записи не было. И там лежат значения после стирания.

Попробуйте эксперимент: передать массив любых чисел кроме нулевых. Т.е. чтобы ни в данных ни в хвосте не было нулей. И напишите что получиться.

Пробовал. Пишется опять же 8 байт, остального нет.
Сергей Борщ
Где-то путаницы (unsigned char *) <->(int *) не может быть? 32 / sizeof(int) = 8. Попробуйте записать, скажем, 28 байт.
Akscan
Цитата(Сергей Борщ @ Nov 9 2016, 11:19) *
Где-то путаницы (unsigned char *) <->(int *) не может быть? 32 / sizeof(int) = 8. Попробуйте записать, скажем, 28 байт.

Писал разное количество, и 31 и 26, и т.д.

Код функций на инициализацию, чтение, запись, и прочее:
Файл memory.c
CODE

#ifndef AT91RM9200_H
#include <AT91RM9200.H>
#endif
#include "memory.h"
#define PAGE_SIZE 2112
extern unsigned char data[PAGE_SIZE];
extern int statusReadPageNand;
extern unsigned char writeData[30];


void delayNand(int a)
{
while(a!=0)
{
a--;
}
}

void BOARD_ConfigureNandFlash(void)
{

// Configure EBI
AT91C_BASE_EBI->EBI_CSA |= AT91C_EBI_CS3A_SMC_SmartMedia;

// Setup Flash
// WSEN = 1 (Wait states are enabled)
// NWS = 1 (Number of Wait States) (1 * 16,7 nS)
// DBW = 2 (Data Bus Width - 8-bit)
AT91C_BASE_SMC2->SMC2_CSR[3] = (AT91C_SMC2_NWS & 1) | AT91C_SMC2_WSEN | AT91C_SMC2_DBW_8;

}

void PIO_Configure_CE_RB(void)
{
//PC14=SMCE - output
AT91C_BASE_PIOC->PIO_IDR = AT91C_PIO_PC14; //Disable interrupts
AT91C_BASE_PIOC->PIO_PPUDR = AT91C_PIO_PC14;
AT91C_BASE_PIOC->PIO_MDDR = AT91C_PIO_PC14;
AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC14; //1
AT91C_BASE_PIOC->PIO_OER = AT91C_PIO_PC14;
AT91C_BASE_PIOC->PIO_PER = AT91C_PIO_PC14;

//SMWE - output
AT91C_BASE_PIOC->PIO_MDDR = AT91C_PIO_PC3;
AT91C_BASE_PIOC->PIO_PDR = AT91C_PIO_PC3;
AT91C_BASE_PIOC->PIO_ASR = AT91C_PIO_PC3;

//SMOE - output
AT91C_BASE_PIOC->PIO_MDDR = AT91C_PIO_PC1;
AT91C_BASE_PIOC->PIO_PDR = AT91C_PIO_PC1;
AT91C_BASE_PIOC->PIO_ASR = AT91C_PIO_PC1;

//PC15=SMRB - input
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOC;
AT91C_BASE_PIOC->PIO_IDR = AT91C_PIO_PC15; //Disable interrupts
AT91C_BASE_PIOC->PIO_PPUDR = AT91C_PIO_PC15;
AT91C_BASE_PIOC->PIO_IFDR = AT91C_PIO_PC15;
AT91C_BASE_PIOC->PIO_ODR = AT91C_PIO_PC15;
AT91C_BASE_PIOC->PIO_PER = AT91C_PIO_PC15;
}

unsigned char Get_SMRB(void)
{
unsigned int reg = AT91C_BASE_PIOC->PIO_PDSR;

if ((reg & AT91C_PIO_PC15) == 0) {
return 0;
}
else {
return 1;
}
}

void WaitReady(void)
{
while (!Get_SMRB());
}


void NandFlash_Reset(void)
{
// PC14 #CE=0
AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC14; //0

WRITE_COMMAND(COMMAND_RESET);
WaitReady();
// PC14 #CE=1
AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC14; //1
}


int NandFlash_ReadId(void)
{
unsigned int chipId;
unsigned char chipId2;

// PC14 #CE=0
AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC14; //0

WRITE_COMMAND(COMMAND_READID);
WRITE_ADDRESS(0);
chipId = READ_DATA8;
if (chipId == 0x2C)
{
AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC14; //1
return 1;
}
chipId |= READ_DATA8 << 8;
chipId |= READ_DATA8 << 16;
chipId |= READ_DATA8 << 24;
chipId2 = READ_DATA8;
// PC14 #CE=1
AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC14; //1
if(chipId==0)
chipId=10;
if(chipId2==0)
chipId2=10;
return chipId;
}

void NandFlash_Read(int column, int row, int page, int LUN, int plane)
{
int column1,column2,row1,row2,row3;
int i = 0;

int cycle1,cycle2,cycle3,cycle4,cycle5;
cycle1 = column%65536;
cycle2 = column>>16;

cycle3 = page;
cycle3 |= plane<<7;

cycle4 = row%65536;
cycle5 = row>>9;
cycle5 |= LUN<<10;

// PC14 #CE=0
AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC14; //0

WRITE_COMMAND(COMMAND_READ_1);

WRITE_ADDRESS(cycle1);
WRITE_ADDRESS(cycle2);

WRITE_ADDRESS(cycle3);
WRITE_ADDRESS(cycle4);
WRITE_ADDRESS(cycle5);

WRITE_COMMAND(COMMAND_READ_2);

WaitReady();
for(i = 0; i<PAGE_SIZE; i++)
{
data[i] = READ_DATA8;
delayNand(1);
data[i] |= READ_DATA8 << 8;
delayNand(1);
data[i] |= READ_DATA8 << 16;
delayNand(1);
data[i] |= READ_DATA8 << 24;
delayNand(1);
}
// PC14 #CE=1
AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC14; //1
}


void NandFlash_Write(int column, int row, int page, int LUN, int plane)
{
// PC14 #CE=0
int column1,column2,row1,row2,row3,i;
int cycle1,cycle2,cycle3,cycle4,cycle5;
unsigned char * Write;
Write = (unsigned char *) writeData;


cycle1 = column%65536;
cycle2 = column>>16;

cycle3 = page;
cycle3 |= plane<<7;

cycle4 = row%65536;
cycle5 = row>>9;
cycle5 |= LUN<<10;




AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC14; //0
WRITE_COMMAND(COMMAND_WRITE_1);



WRITE_ADDRESS(cycle1);
WRITE_ADDRESS(cycle2);

WRITE_ADDRESS(cycle3);
WRITE_ADDRESS(cycle4);
WRITE_ADDRESS(cycle5);

for(i = 10;i>0;i--)
{
WRITE_DATA8(Write[i]);
delayNand(1);
}

WRITE_COMMAND(COMMAND_WRITE_2);
WaitReady();
// PC14 #CE=1
AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC14; //1
}



unsigned char NandFlash_ReadStatus()
{
int status;
AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC14; //0
WRITE_COMMAND(COMMAND_READ_STATUS);
status = READ_DATA8;
WaitReady();


AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC14; //1
return status;
}

void NandFlash_EraseBlock(int column, int page, int plane)
{
unsigned char status;
int cycle1,cycle2,cycle3;

cycle1 = column%65536;
cycle2 = column>>16;

cycle3 = page;
cycle3 |= plane<<7;

AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC14; //0

WRITE_COMMAND(COMMAND_ERASE_1);

WRITE_ADDRESS(cycle1);
WRITE_ADDRESS(cycle2);
WRITE_ADDRESS(cycle3);

WRITE_COMMAND(COMMAND_ERASE_2);
WaitReady();
AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC14; //1

status = NandFlash_ReadStatus();

}
void NandFlash_WriteFF(int column,int row, int page, int LUN, int plane)
{
// PC14 #CE=0
int column1,column2,row1,row2,row3,i;
int cycle1,cycle2,cycle3,cycle4,cycle5;
unsigned char * Write;
Write = (unsigned char *) writeData;


cycle1 = column%65536;
cycle2 = column>>16;

cycle3 = page;
cycle3 |= plane<<7;

cycle4 = row%65536;
cycle5 = row>>9;
cycle5 |= LUN<<10;




AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC14; //0
WRITE_COMMAND(COMMAND_WRITE_1);



WRITE_ADDRESS(cycle1);
WRITE_ADDRESS(cycle2);

WRITE_ADDRESS(cycle3);
WRITE_ADDRESS(cycle4);
WRITE_ADDRESS(cycle5);

for(i = 2112;i>0;i--)
{
WRITE_DATA8(0xFF);
delayNand(1);
}

WRITE_COMMAND(COMMAND_WRITE_2);
WaitReady();
// PC14 #CE=1
AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC14; //1
}

Файл memory.h
CODE

#ifndef MEMORY_H
#define MEMORY_H
#endif
#define COMMAND_RESET 0xFF
#define COMMAND_READID 0x90
#define COMMAND_READ_1 0x00
#define COMMAND_READ_2 0x30
#define COMMAND_WRITE_1 0x80
#define COMMAND_WRITE_2 0x10
#define COMMAND_ERASE_1 0x60
#define COMMAND_ERASE_2 0xD0
#define COMMAND_READ_STATUS 0x70


/// Address for transferring command bytes to the nandflash.
#define BOARD_NF_COMMAND_ADDR 0x40200000
/// Address for transferring address bytes to the nandflash.
#define BOARD_NF_ADDRESS_ADDR 0x40400000
/// Address for transferring data bytes to the nandflash.
#define BOARD_NF_DATA_ADDR 0x40000000


#define WRITE_COMMAND(command) \
{*((volatile unsigned char *) BOARD_NF_COMMAND_ADDR) = (unsigned char) command;}
#define WRITE_ADDRESS(address) \
{*((volatile unsigned char *) BOARD_NF_ADDRESS_ADDR) = (unsigned char) address;}
#define WRITE_DATA8(data) \
{*((volatile unsigned char *) BOARD_NF_DATA_ADDR) = (unsigned char) data;}
#define READ_DATA8 \
(*((volatile unsigned char *) BOARD_NF_DATA_ADDR))

void BOARD_ConfigureNandFlash(void);
void PIO_Configure_CE_RB(void);
unsigned char Get_SMRB(void);
void WaitReady(void);
void NandFlash_Reset(void);
int NandFlash_ReadId(void);
void NandFlash_Write(int column,int row, int page, int LUN, int plane);
void NandFlash_Read(int column,int row, int page, int LUN, int plane);
unsigned char NandFlash_ReadStatus();
void NandFlash_EraseBlock(int column, int page, int plane);
void NandFlash_WriteFF(int column,int row, int page, int LUN, int plane);

MegaVolt
Если я правильно понимаю этот кусочек пишет 10 байт. Всегда вне зависимости от реально длинны данных. Правда не 8.....

Код
        for(i = 10;i>0;i--)
        {
            WRITE_DATA8(Write[i]);
            delayNand(1);
        }
Akscan
Цитата(MegaVolt @ Nov 9 2016, 11:49) *
Если я правильно понимаю этот кусочек пишет 10 байт. Всегда вне зависимости от реально длинны данных. Правда не 8.....

Код
        for(i = 10;i>0;i--)
        {
            WRITE_DATA8(Write[i]);
            delayNand(1);
        }

Я его менял, когда разные значение писать пробовал
MegaVolt
Осциллограф видит все импульсы записи?
Сергей Борщ
QUOTE (Akscan @ Nov 9 2016, 11:28) *
Писал разное количество, и 31 и 26, и т.д.
Типичный ответ программиста - точный и не несущий никакой полезной информации sm.gif И каков был результат этих записей? Писалось все равно 8? Больше? Меньше?
Akscan
Цитата(Сергей Борщ @ Nov 9 2016, 12:10) *
Типичный ответ программиста - точный и не несущий никакой полезной информации sm.gif И каков был результат этих записей? Писалось все равно 8? Больше? Меньше?

Ну бывает)
Точно 8.

Цитата(MegaVolt @ Nov 9 2016, 12:00) *
Осциллограф видит все импульсы записи?

Да, сейчас проверил, импульсы видны все.
MegaVolt
Цитата(Akscan @ Nov 9 2016, 13:29) *
Да, сейчас проверил, импульсы видны все.
Неожиданно. Повторная запись без стирания что даёт?
Akscan
Цитата(MegaVolt @ Nov 9 2016, 15:52) *
Неожиданно. Повторная запись без стирания что даёт?

Ничего не дает, хотя и пробовал. По даташиту на микросхему, стирание перед записью обязательно.
Есть подозрение, что стирание не выполняется, но тогда это выплыло бы в проверке статуса, а она проходит успешно
Akscan
Нашелся один косяк в разводке платы. Две ноги запаяны неправильно.
Всем большое спасибо за помощь, буду копать дальше. Если что, подниму тему.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.