|
Пример работы с AT25DF641., Может у кого есть готовый исходник? |
|
|
|
May 21 2010, 13:44
|
Группа: Участник
Сообщений: 3
Регистрация: 22-03-10
Пользователь №: 56 121

|
Не поможет ли кто примерчиком общения с AT25DF641 флэшкой? Хочется побыстрее её запустуть, потому что дальше интереснее... но не получается. Взял пример от Атмела для АТ26, но он не работает. AT26_ReadJedecId(&at26); всегда возвращает 0. Вроде как всё просто, но как-то глухо
|
|
|
|
|
May 21 2010, 14:10
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(tMauzer @ May 21 2010, 16:44)  Хочется побыстрее её запустуть, потому что дальше интереснее... но не получается. Если не понимаете, даже с примером, как оно работает, то дальше будет не интереснее, а просто хуже. Посему не надо торопится. Разбирайтесь спокойно. Ну а поскольку Вы спрашиваете на как 2*2 написать, а как работать с железом, то для начала разберитесь, чем Ваше неназванное железо отличается от того, которое в "пример от Атмела".
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
May 21 2010, 14:36
|
Группа: Участник
Сообщений: 3
Регистрация: 22-03-10
Пользователь №: 56 121

|
Железо - это практически копия at91sam7x-ek. На SPI0 на CS1 сидит флешка AT25DF641.
Я взял spi-flash/at26.h библиотечку с Атмела. В ней, правда, небыло AT25DF641 в at26Devices[]. Я её добавил, но это не принципиально поску до этого не доходит посколку я неполучаю ответ на команду 0x9F.
Сижу разбираюсь с библиотечкой, но библиотека at26.h + драйвер spid.h + ещё несколько необходимых для этого библиотечек (pio, aic, trace, math и т.д.) - как-то немного сильно покручено. Хотел спросить, может есть у кого-то пример по проще.
|
|
|
|
|
May 21 2010, 14:46
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(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++); }
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
May 21 2010, 14:51
|
Группа: Участник
Сообщений: 3
Регистрация: 22-03-10
Пользователь №: 56 121

|
AHTOXA, ОГРОМНОЕ СПАСИБО!!! А в амеловских доках написано: "The AT25DF641 is a serial interface Flash memory device".
Сообщение отредактировал tMauzer - May 21 2010, 15:35
|
|
|
|
|
Dec 4 2010, 18:05
|
Группа: Новичок
Сообщений: 1
Регистрация: 4-12-10
Пользователь №: 61 404

|
Цитата(tMauzer @ May 21 2010, 20:51)  AHTOXA, ОГРОМНОЕ СПАСИБО!!!
А в амеловских доках написано: "The AT25DF641 is a serial interface Flash memory device". :unsure: Не подскажете где вы взяли библиотеку spi-flash/at26.h..? и какой компилятор
|
|
|
|
|
Sep 7 2011, 06:47
|
Участник

Группа: Свой
Сообщений: 65
Регистрация: 9-02-11
Из: Трехгорный
Пользователь №: 62 814

|
Здравствуйте! Не буду создавать новую тему, спрошу тут: У меня 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 - тишина...
Сообщение отредактировал yurmala - Sep 7 2011, 07:12
|
|
|
|
|
Sep 7 2011, 08:23
|
Участник

Группа: Свой
Сообщений: 65
Регистрация: 9-02-11
Из: Трехгорный
Пользователь №: 62 814

|
Цитата(AHTOXA @ Sep 7 2011, 13:58)  Не устану повторять: SPI - такая штука: Чтобы что-то прочитать, надо что-то записать! Хм....кажется начал понимать. В SPI (SSP) регистр сдвиговый. Байт записал - байт прочитал?
Сообщение отредактировал yurmala - Sep 7 2011, 08:39
|
|
|
|
|
Sep 7 2011, 09:06
|
Участник

Группа: Свой
Сообщений: 65
Регистрация: 9-02-11
Из: Трехгорный
Пользователь №: 62 814

|
Как-то странно все пока... Поменял код: Код 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 - Sep 7 2011, 09:18
|
|
|
|
|
Sep 7 2011, 10:27
|
Участник

Группа: Свой
Сообщений: 65
Регистрация: 9-02-11
Из: Трехгорный
Пользователь №: 62 814

|
Получилось вот с таким кодом. Но не могу понять откуда возникает первый непонятный байт, который я считываю в 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); }
|
|
|
|
|
Sep 7 2011, 10:53
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(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); ...
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Sep 7 2011, 11:12
|
Участник

Группа: Свой
Сообщений: 65
Регистрация: 9-02-11
Из: Трехгорный
Пользователь №: 62 814

|
Да. Получилось. Спасибо. А как тогда эта система работает при чтении/записи произвольных данных? Ведь там надо еще 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); }
Сообщение отредактировал yurmala - Sep 7 2011, 11:19
|
|
|
|
|
Sep 8 2011, 04:41
|
Участник

Группа: Свой
Сообщений: 65
Регистрация: 9-02-11
Из: Трехгорный
Пользователь №: 62 814

|
Цитата(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; }
|
|
|
|
|
Sep 8 2011, 05:34
|
Участник

Группа: Свой
Сообщений: 65
Регистрация: 9-02-11
Из: Трехгорный
Пользователь №: 62 814

|
Цитата(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); }
|
|
|
|
|
Sep 8 2011, 06:28
|
Участник

Группа: Свой
Сообщений: 65
Регистрация: 9-02-11
Из: Трехгорный
Пользователь №: 62 814

|
Цитата(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); }
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|