Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Пример работы с AT25DF641.
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
tMauzer
Не поможет ли кто примерчиком общения с AT25DF641 флэшкой?

Хочется побыстрее её запустуть, потому что дальше интереснее... но не получается.

Взял пример от Атмела для АТ26, но он не работает. AT26_ReadJedecId(&at26); всегда возвращает 0.

Вроде как всё просто, но как-то глухо laughing.gif
zltigo
Цитата(tMauzer @ May 21 2010, 16:44) *
Хочется побыстрее её запустуть, потому что дальше интереснее... но не получается.

Если не понимаете, даже с примером, как оно работает, то дальше будет не интереснее, а просто хуже.
Посему не надо торопится. Разбирайтесь спокойно. Ну а поскольку Вы спрашиваете на как 2*2 написать, а как работать с железом, то для начала разберитесь, чем Ваше неназванное железо отличается от того, которое в "пример от Атмела".
tMauzer
Железо - это практически копия at91sam7x-ek. На SPI0 на CS1 сидит флешка AT25DF641.

Я взял spi-flash/at26.h библиотечку с Атмела. В ней, правда, небыло AT25DF641 в at26Devices[]. Я её добавил, но это не принципиально поску до этого не доходит посколку я неполучаю ответ на команду 0x9F.

Сижу разбираюсь с библиотечкой, но библиотека at26.h + драйвер spid.h + ещё несколько необходимых для этого библиотечек (pio, aic, trace, math и т.д.) - как-то немного сильно покручено. Хотел спросить, может есть у кого-то пример по проще.
AHTOXA
Цитата(tMauzer @ May 21 2010, 19:44) *
Не поможет ли кто примерчиком общения с AT25DF641 флэшкой?


AT25 - EEPROM, AT26 - FLASH. Вот о чём пытался намекнуть вам zltigo.

Вот минимальный набор для работы с at25:
Код
#include "at25.h"

#define AT25_CS        3, 3, L            // at25 чипселект

// EEPROM commands
#define  EE_READ              3
#define  EE_WRITE             2
#define  EE_WREN              6
#define  EE_WRDI              4
#define  EE_RDSR              5
#define  EE_WRSR              1

// EEPROM status
#define SS_WRITING            0x01    // Write cycle in progress
#define SS_WRITE_ENABLE        0x02    // Write enabled

void at25_init(void)
{
    direct(AT25_CS,O);    // переключаем ногу чипселекта на выход
    off(AT25_CS);           // отключаем (высокий уровень)
}

void at25_command(char cmd)
{
    on(AT25_CS);
    spi_w(cmd);
}

uint8_t at25_read_status(void)
{
    int result;

    at25_command(EE_RDSR);
    result = spi_r8();
    off(AT25_CS);
    return result;
}

uint8_t at25_read_byte(uint16_t adr)
{
    uint8_t result;

    at25_command(EE_READ);
    spi_w(adr >> 8);
    spi_w(adr);
    result = spi_r8();
    off(AT25_CS);
    return result;
}

void at25_read(uint16_t adr, uint8_t *bf, uint16_t len)
{
    at25_command(EE_READ);
    spi_w(adr >> 8);
    spi_w(adr);
    while (len--)
        *bf++ = spi_r8();
    off(AT25_CS);
}

void at25_write_byte(uint16_t adr, uint8_t data)
{
    at25_command(EE_WREN);
    off(AT25_CS);            // toggle CS, necessary for WREN

    at25_command(EE_WRITE);
    spi_w(adr >> 8);
    spi_w(adr);
    spi_w(data);
    off(AT25_CS);
    while (at25_read_status()& SS_WRITING);
}

void at25_write(uint16_t adr, uint8_t *bf, uint16_t len)
{
    while (len--)
        at25_write_byte(adr++, *bf++);
}
tMauzer
AHTOXA, ОГРОМНОЕ СПАСИБО!!!

А в амеловских доках написано: "The AT25DF641 is a serial interface Flash memory device". unsure.gif
GrigaN
Цитата(tMauzer @ May 21 2010, 20:51) *
AHTOXA, ОГРОМНОЕ СПАСИБО!!!

А в амеловских доках написано: "The AT25DF641 is a serial interface Flash memory device". :unsure:



Не подскажете где вы взяли библиотеку spi-flash/at26.h..? и какой компилятор
Genadi Zawidowski
at91lib_20100901_softpack_1_9_v_1_0_svn_v15011.zip

в 1.7 тоже есть. Может быть и в 1.5

http://www.atmel.com/dyn/products/tools_ca...sp?tool_id=4343
yurmala
Здравствуйте! Не буду создавать новую тему, спрошу тут:
У меня LPC2468 и микросхема AT25DF321A подключенная по SSP1.
Пытаюсь заставить ее работать, но не в какую (не могу даже получить Manufacture ID, приходит в ответ или 0x00 или 0xFF). Уже перекурил даташиты несколько раз (и на контроллер и на память).
Инициализация SSP1
Код
DWORD SSP1Init( void )
{
  BYTE i, Dummy=Dummy;

  PCONP    |=  (1 << 10); // PCSSP1
  PCLKSEL0 |=  (1 << 20);  // Peripheral Clock Selection for SSP1 <3=> Pclk = Cclk
  PINSEL9  &= ~(3 << 10);            // Set SSEL to GPIO pin
  PINSEL9  |=  (3 << 8) | (3 << 12) | (3 << 14);     // P4.20 - SCK1, P4.22 - MISO1, P4.23 - MOSI1

  FPIN_AS_OUTPUT_(4,21);
  FPIN_SET_(4,21);
  
  SSP1CR0  = 0x0707;//(7 << 0) | (1 << 6) | (1 << 7) | (1 << 8);//0x0707; // Set DSS data to 8-bit, Frame format SPI, CPOL = 0, CPHA = 0, and SCR is 15
  
  SSP1CPSR = 0x02;

  for ( i = 0; i < FIFOSIZE; i++ )
  {Dummy = SSP1DR;}        // clear the RxFIFO

  SSP1CR1  = SSPCR1_SSE; // Device select as master, SSP Enabled

  return( TRUE );

}


Теперь сам код запроса:
Код
volatile int Flash1_ManID,Flash1_MemType1,Flash1_MemType2,Flash1_MemSize = 0;

void Flash1_ReadType(void)
{
    FPIN_CLR_(4,21);
    SSP1DR = 0x9F;
    while ( !(SSP1SR & SSPSR_BSY) );   // SSPSR_TFE SSPSR_RNE
    Flash1_ManID     = SSP1DR;
    Flash1_MemType1     = SSP1DR;
    Flash1_MemType2     = SSP1DR;
    Flash1_MemSize     = SSP1DR;
    FPIN_SET_(4,21);
}


В итоге из SSP1DR идут одни нули...(изредка один из байтов - 0xFF)
Вначале думал что проблема в скорости - перебирал в регистре SSP1CR0 значения: 0x0107, 0x0707, 0x0007; перебирал значения в регистре SSP1CPSR: 0x01 до 0x40
Но с другой стороны AT25DF321A работает до 100 МГц, а у меня максимум что получалось - 18МГц (Master Clock в окне отладки Keil)
Уперся в эту хрень и уже 2 дня не могу ничего сделать...
Где же я ошибся?

Добавлено: Проверяю на осциллографе - SCK работает - четко 8 тактов. Но на MISO - тишина...
AHTOXA
Не устану повторять:
SPI - такая штука:
Чтобы что-то прочитать,
надо что-то записать!
yurmala
Цитата(AHTOXA @ Sep 7 2011, 13:58) *
Не устану повторять:
SPI - такая штука:
Чтобы что-то прочитать,
надо что-то записать!


Хм....кажется начал понимать. В SPI (SSP) регистр сдвиговый. Байт записал - байт прочитал?
AHTOXA
Именно! sm.gif
yurmala
Как-то странно все пока...
Поменял код:
Код
volatile unsigned int ManID,MemType,MemType1,MemType2,MemSize;

void Flash_ReadType(void)
{
    FPIN_CLR(4,21);
    SSP1DR = 0x9F;
    SSP1DR = 0;
    SSP1DR = 0;
    while ( !(SSP1SR & SSPSR_BSY) );
    ManID = SSP1DR;      // В SSP1DR 0xFF, но при чтении в переменную попадает 0x1F
    MemType = SSP1DR; // В SSP1DR 0x47, но при чтении в переменную попадает 0x01
    MemSize = SSP1DR;  // В SSP1DR 0x01, но при чтении в переменную попадает 0x00
    FPIN_SET(4,21);
}


Если выполнять пошагово - в дебаггере Keil вижу в регистре SSP1DR нужные данные - 1F,47,01, да и то - не всегда. Иногда вижу 1F и 01, а 47 теряется...
А если в отладчике выполнить функцию целиком (F10) то в переменные записываются нули...
yurmala
Получилось вот с таким кодом. Но не могу понять откуда возникает первый непонятный байт, который я считываю в Dummy.
Может я это как-то не так понял?

Считывание ManufactureID
Код
volatile unsigned int ManID,MemType,MemType1,MemType2,MemSize;

void Flash_ReadType(void)
{
    BYTE Dummy = Dummy;

    FPIN_CLR(4,21);
    SSP1DR = 0x9F;
    SSP1DR = 0;
    SSP1DR = 0;
    SSP1DR = 0;
    while ( !(SSP1SR & SSPSR_BSY) );
    Dummy   = SSP1DR;  // Всегда 0xFF    
    ManID   = SSP1DR;    
    MemType = SSP1DR;    
    MemSize = SSP1DR;    
    FPIN_SET(4,21);
}

Считывание 2-х байтного статусного регистра
Код
volatile unsigned int RegStat1,RegStat2;

void Flash_ReadStatus(void)
{
    BYTE Dummy = Dummy;

    FPIN_CLR(4,21);
    SSP1DR = 0x05;
    SSP1DR = 0;
    while ( !(SSP1SR & SSPSR_BSY) );
    Dummy    = SSP1DR; // Всегда 0xFF    
    RegStat1 = SSP1DR;    
    RegStat2 = SSP1DR;    
    FPIN_SET(4,21);
}
AHTOXA
Цитата(yurmala @ Sep 7 2011, 16:27) *
Может я это как-то не так понял?

Не так. Последовательность записал - прочитал надо выполнять для каждого байта.
Я не работал с LPC2468, но исходя из общих соображений должно быть как-то так:
Код
uint8_t spi_rw(uint8_t b)
{
    SSP1DR = b;   // передаём
    while ( !(SSP1SR & SSPSR_RNE) );  // ждём пока примется
    return SSP1DR;
}

...
    spi_rw(0x9F);
    ManID   = spi_rw(0);
    MemType = spi_rw(0);
    MemSize = spi_rw(0);
...
yurmala
Да. Получилось. Спасибо.

А как тогда эта система работает при чтении/записи произвольных данных?

Ведь там надо еще 3 байта адреса передавать + 2 dummy байта?
Как это будет выглядеть? Так что ли?
Чтение данных с адреса Х
Код
spi_rw(0x1B);
spi_rw(X >> 16);
spi_rw(X >> 8);
spi_rw(X);
spi_rw(0); //dummy 1
spi_rw(0); //dummy 2
for (...)
   {
   buf++ = spi_rw(0);
   }
AHTOXA
Да, именно. (В четвёртом сообщении темы есть пример)
yurmala
Цитата(AHTOXA @ Sep 7 2011, 17:16) *
Да, именно. (В четвёртом сообщении темы есть пример)

Я его изначально за основу и взял, если честно. Но неопределенность с функциями spi_r8 и spi_w привела в тупик.
Вот сейчас не получается добиться того чтобы прочитать из микросхемы записанный ранее байт.
Функция записи получилась такая:
Код
uint8_t ssp_rw(uint8_t b)
{
    SSP1DR = b;   // передаём
    while ( !(SSP1SR & SSPSR_RNE) );  // ждём пока примется
    return SSP1DR;
}

void at25_command(char cmd)
{
    at25_SSEL_low(AT25_CS);
    ssp_rw(cmd);
}

void at25_write_byte(uint32_t adr, uint8_t data)
{
    at25_command(EE_WREN);
    at25_SSEL_high(AT25_CS);            // toggle CS, necessary for WREN

    at25_command(EE_WRITE);
    ssp_rw(adr >> 16);
    ssp_rw(adr >>  8);
    ssp_rw(adr);
    ssp_rw(data);
    at25_SSEL_high(AT25_CS);
    while (at25_read_status()& SS_WRITING);
}


Функция at25_write_byte() вроде отрабатывает без ошибок.

Но при чтении этого байта - вместо мною записанного байта возвращается 0xFF

Функция чтения:
Код
uint8_t at25_read_byte(uint32_t adr)
{
    uint8_t result;

    at25_command(EE_READ);
    ssp_rw(adr >> 16);
    ssp_rw(adr >> 8);
    ssp_rw(adr);
    result = ssp_rw(0);
    at25_SSEL_high(AT25_CS);
    return result;
}

AHTOXA
Да вроде правильно всё... Может, ножка WP случайно на землю попала?

ЗЫ. Обратите внимание, пример - для EEPROM, а у вас - FLASH. В EEPROM можно писать данные поверх старых значений, а FLASH надо стирать перед записью.
yurmala
Цитата(AHTOXA @ Sep 8 2011, 11:21) *
Да вроде правильно всё... Может, ножка WP случайно на землю попала?

это нет. у нас WP аппаратно висит на 3.3V
Цитата(AHTOXA @ Sep 8 2011, 11:21) *
ЗЫ. Обратите внимание, пример - для EEPROM, а у вас - FLASH. В EEPROM можно писать данные поверх старых значений, а FLASH надо стирать перед записью.

Вот как у меня выполняется:
Код
...
at25_erase_4kb(0);
at25_write_byte(0,22);
read_byte = at25_read_byte(0);

...

void at25_erase_4kb(uint32_t adr)
{
    at25_command(EE_WREN);
    at25_SSEL_high(AT25_CS);            // toggle CS, necessary for WREN

    at25_command(EE_ERASE4); // 0х20
    ssp_rw(adr >> 16);
    ssp_rw(adr >>  8);
    ssp_rw(adr);
    at25_SSEL_high(AT25_CS);
    while (at25_read_status()& SS_WRITING);
}

AHTOXA
Не вижу ошибок. Unprotect Sector - вряд ли. Global Protect/Unprotect - тем более.
Остаётся посмотреть осциллографом, может всё-таки функция ssp_rw() как-то не так работает. (Или дождаться того, кто работал с LPC2468)
yurmala
Цитата(AHTOXA @ Sep 8 2011, 12:04) *
Не вижу ошибок. Unprotect Sector - вряд ли. Global Protect/Unprotect - тем более.
Остаётся посмотреть осциллографом, может всё-таки функция ssp_rw() как-то не так работает. (Или дождаться того, кто работал с LPC2468)

AHTOXA, ты прав. Sector Protect Register выдал мне 0xFF - сектор защищен. Unprotect Sector помог. Спасибо тебе огромное.

Добавленные функции:

Код
uint8_t at25_read_protect_register(uint32_t adr)
{
uint8_t result;
    at25_command(EE_RDPR);
    ssp_rw(adr >> 16);
    ssp_rw(adr >> 8);
    result = ssp_rw(adr);
    result = ssp_rw(0);
    at25_SSEL_high(AT25_CS);
    return result;
}

void at25_Unprotect_Sector(uint32_t adr)
{
    at25_command(EE_WREN);
    at25_SSEL_high(AT25_CS);            // toggle CS, necessary for WREN

    at25_command(EE_UNPROTECT);
    ssp_rw(adr >> 16);
    ssp_rw(adr >>  8);
    ssp_rw(adr);
    at25_SSEL_high(AT25_CS);
    while (at25_read_status()& SS_WRITING);
}
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.