|
Проблемы с записью/считыванием во/из Flash, Коряво пишутся или считываются данные |
|
|
|
Nov 1 2006, 15:14
|
Участник

Группа: Новичок
Сообщений: 19
Регистрация: 12-07-06
Пользователь №: 18 762

|
Проблема состоит в том, что по уарту приходят данные и записываются в буфер, который я пытаюсь записать во флеш и, соответственно, считать из флеша. Так вот записываю я одни данные, а считываются другие, вернее, происходит какая-то странная подмена одних байтов другими. К примеру(все в шестнадцатиричном виде): | Записываю | Считываю | | 0F | F0 | | EA | 57 | | FE | 7F | и т.п. Вот функции, которыми пользуюсь для записи, считывани во и из flash Код
__ramfunc void EFC_Init(void) { while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY)); AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(100 << 16)) | AT91C_MC_FWS_1FWS; while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY)); } Код
__ramfunc unsigned int EFC_WritePage(unsigned int adr, unsigned int *pbuf) { unsigned int *pflash; unsigned int page; unsigned int region; unsigned int i;
pflash = (unsigned int *)adr; page = (adr & 0x3FFFF) / EFC_PAGE_SIZE; region = (page/EFC_PagesInTheLockRegion);
EFC_Init();
if (AT91C_BASE_MC->MC_FSR & (region << 16)) { // lock set, clear it AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(50 << 16)) | AT91C_MC_FWS_2FWS; AT91C_BASE_MC->MC_FCR = (0x5A << 24) | (region << 8 ) | AT91C_MC_FCMD_UNLOCK; }
while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY)); for (i = 0; i < EFC_PAGE_SIZE_UINT; i++) if (pbuf[i] != 0) { *(pflash + i) = *(pbuf + i); }
AT91C_BASE_MC->MC_FCR = (0x5A << 24) | (page << 8 ) | AT91C_MC_FCMD_START_PROG; while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY));
return 1; } Код
__ramfunc void TestEFC(unsigned int adr) {
AT91F_AIC_DisableIt (AT91C_BASE_AIC, AT91C_ID_US1); AT91F_AIC_DisableIt (AT91C_BASE_AIC, AT91C_ID_PIOA);
while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY)); EFC_WritePage(0x100000 | adr, (unsigned int*)tryInt);
AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_US1); AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_PIOA); Код __ramfunc ReadFromAddress(unsigned int address) { AT91F_AIC_DisableIt (AT91C_BASE_AIC, AT91C_ID_US1); AT91F_AIC_DisableIt (AT91C_BASE_AIC, AT91C_ID_PIOA);
while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY)); EFC_ReadPage(address, buff_tx);
while(!(AT91F_US_TxReady(AT91C_BASE_US1))); AT91F_US_Put(buff_tx, EFC_PAGE_SIZE);
AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_US1); AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_PIOA);
COM1->US_TPR = (unsigned char)&buff_tx[0]; COM1->US_TCR = 0;
} Прогаю sam7s256 в iar.
|
|
|
|
|
Nov 1 2006, 15:43
|

Мастер
   
Группа: Свой
Сообщений: 730
Регистрация: 18-02-06
Из: Москва
Пользователь №: 14 474

|
Цитата(Redaer @ Nov 1 2006, 18:14)  ... Бит-реверсия получается, однако... А вы уверены что это ошибка во флеш, а не в УАРТе? Иначе говоря, УАРТ проверен, в нем есть уверенность?
--------------------
شامل
|
|
|
|
|
Nov 1 2006, 20:09
|
Участник

Группа: Новичок
Сообщений: 19
Регистрация: 12-07-06
Пользователь №: 18 762

|
Ха! Действительно, как не заметил... Если посылаю с компа на комп по КОМ-порту, то все корректно приходит, без реверсии... То же самое наблюдается и в ИАРе, когда пошагово выполняю, т.е. в RX-массиве оказываются верные 4-хбайтовые числа... Получается, что меняются старшие и младшие биты местами... Вернее считывание числа из массива происходит наоборот... А как-нть этого можно избежать? Edmundo, cпасибо за подсказку, буд дальше мучать
Сообщение отредактировал Redaer - Nov 1 2006, 20:11
|
|
|
|
|
Nov 1 2006, 20:27
|

Мастер
   
Группа: Свой
Сообщений: 730
Регистрация: 18-02-06
Из: Москва
Пользователь №: 14 474

|
Цитата(Redaer @ Nov 1 2006, 23:09)  Получается, что меняются старшие и младшие биты местами... Вернее считывание числа из массива происходит наоборот... А как-нть этого можно избежать? Edmundo, cпасибо за подсказку, буд дальше мучать  Интуитивно мне кажется, что при работе с флеш бит-реверсии получиться не может (справедливости ради скажу, что в SAM'ах флешку не щупал). А вот при работе с последовательными интерфейсами -- запросто  , сами понимаете.
--------------------
شامل
|
|
|
|
|
Nov 2 2006, 14:00
|
Участник

Группа: Новичок
Сообщений: 19
Регистрация: 12-07-06
Пользователь №: 18 762

|
Цитата(Edmundo @ Nov 1 2006, 23:27)  Цитата(Redaer @ Nov 1 2006, 23:09)  Получается, что меняются старшие и младшие биты местами... Вернее считывание числа из массива происходит наоборот... А как-нть этого можно избежать? Edmundo, cпасибо за подсказку, буд дальше мучать  Интуитивно мне кажется, что при работе с флеш бит-реверсии получиться не может (справедливости ради скажу, что в SAM'ах флешку не щупал). А вот при работе с последовательными интерфейсами -- запросто  , сами понимаете. Ага, только если на КОМ посылается больше 1 байта, то он передает их в обратном порядке, т.е.: если посылать по кому 0x1234, то он отправит их как 0x3412, а никак не 0x589 -- проверял на арме прием данных происходит так(не пинать  , но дружеский подзатыльник можно  ) Код
unsigned int testAdr = 0x100000;
while(1) { while(!(AT91F_US_RxReady(AT91C_BASE_US1))); //жду, когда что-либо будет на RX TestEFC(testAdr); // Пишу во флешь данные из RX-буфера(массив типа unsigned int buff_rx[64]) testAdr += 0x100; //изменение адреса записи } инициализация буфера на прием Код
AT91C_BASE_US1->US_RPR = (unsigned int)&buff_rx; AT91C_BASE_US1->US_RCR = 64; Вот думаю, может в каком-нть месте произвести реверсию, к примеру, при отправке с компа на уарт арма?.. Есть смысл?
|
|
|
|
|
Nov 2 2006, 18:43
|
Участник

Группа: Новичок
Сообщений: 19
Регистрация: 12-07-06
Пользователь №: 18 762

|
Может быть... В общем, просто реверс в проге, которая скидывает инфу с компа сделал. Вроде работает... Но все равно интересно, че за глюк такой...
|
|
|
|
|
Nov 2 2006, 21:07
|

Мастер
   
Группа: Свой
Сообщений: 730
Регистрация: 18-02-06
Из: Москва
Пользователь №: 14 474

|
Цитата(Redaer @ Nov 2 2006, 21:43)  Может быть... В общем, просто реверс в проге, которая скидывает инфу с компа сделал. Вроде работает... Но все равно интересно, че за глюк такой... Реверс байтов или битов? Здесь необходимо разобраться в проблеме. Если реверс байтов, то посмотрите: не получается ли у вас где-то так, что вы оперируете массивом int'ов (или short'ов) в одном месте, а в другом -- массивом байтов. В этом случае надо четко представлять порядок байтов при расположении в памяти с учетом endian'а. Если битов, то вероятно это неправильное направление передачи по последовательному интерфейсу (есть два варианта: MSB first и LSB first). Я в свое время делал бит-реверсию по алгоритму из книги Уорена мл. для передачи по SPI, так как там возможно лишь MSB first (в отличие от SSC, где порядок можно настроить). Как в УАРТе -- не знаю, не увлекался
--------------------
شامل
|
|
|
|
|
Nov 3 2006, 03:56
|
Местный
  
Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034

|
Цитата(Edmundo @ Nov 3 2006, 02:07)  Я в свое время делал бит-реверсию по алгоритму из книги Уорена А что за алгоритм? Случайно не так: Код BYTE b; b = ((b<<4) & 0xF0) | ((b>>4) & 0x0F); b = ((b<<2) & 0xCC) | ((b>>2) & 0x33); b = ((b<<1) & 0xAA) | ((b>>1) & 0x55); Если нет то расскажите.
|
|
|
|
|
Nov 3 2006, 05:08
|

Мастер
   
Группа: Свой
Сообщений: 730
Регистрация: 18-02-06
Из: Москва
Пользователь №: 14 474

|
Цитата(Alex03 @ Nov 3 2006, 06:56)  А что за алгоритм? Случайно не так: Код BYTE b; b = ((b<<4) & 0xF0) | ((b>>4) & 0x0F); b = ((b<<2) & 0xCC) | ((b>>2) & 0x33); b = ((b<<1) & 0xAA) | ((b>>1) & 0x55); Если нет то расскажите.  Алгоритм такой (он эффективен для однотактового умножения): Код static inline unsigned char BitReverse(unsigned char cByte) { int nU = (cByte*0x00020202), nM = 0x01044010, nS = nU & nM, nT = (nU << 2) & (nM << 1); return ((nS+nT)*0x01001001) >> 24; } Там можно код чуть соптимизировать, уменьшить число операций за счет констант, но меня по производительности устраивало, поэтому оставил форму как из книги
--------------------
شامل
|
|
|
|
|
Nov 3 2006, 07:19
|
Участник

Группа: Новичок
Сообщений: 19
Регистрация: 12-07-06
Пользователь №: 18 762

|
Я реверсию битов сделал
Вот ещё вопрос, когда, во флешь что-то пишешь, её нужно предварительно очистить(как я понял, забить 0xFF). Но во флеше, насколько я знаю, хранится таблица векторов прерываний, она не сотрется? И вообще, какой у нее адрес? З.Ы. Начинаю писать с такого адреса 0x100000
|
|
|
|
|
Nov 4 2006, 15:58
|

Мастер
   
Группа: Свой
Сообщений: 730
Регистрация: 18-02-06
Из: Москва
Пользователь №: 14 474

|
Цитата(Redaer @ Nov 3 2006, 10:19)  Вот ещё вопрос, когда, во флешь что-то пишешь, её нужно предварительно очистить(как я понял, забить 0xFF). Но во флеше, насколько я знаю, хранится таблица векторов прерываний, она не сотрется? И вообще, какой у нее адрес? З.Ы. Начинаю писать с такого адреса 0x100000 Ну это уже вопросы к doc6175. А после внимательного прочтения сюда, если что не ясно.
--------------------
شامل
|
|
|
|
|
Nov 14 2006, 12:48
|
Участник

Группа: Новичок
Сообщений: 19
Регистрация: 12-07-06
Пользователь №: 18 762

|
2vmp, MSBF в нуле... 2Edmundo, как я понял, регистр векторов прерываний находится вот здесь, то есть затереть я его никак не могу своими действиями: Цитата AIC_IVR is mapped at the absolute address 0xFFFFF100 and thus accessible from the ARM interrupt vector at address 0x00000018 [/size]
Можно тогда ещё вопрос по получению информации по уарту и записи её во flash?
Я посылаю 256 байт зараз по уарту и принимаю их в буфер, который потом записываю во flash, так вот... Если просто запускаю программу(слушающую и записывающую), то во flash ничего не пишется(когда читаю из неё, то получаю F0 00 00 00 FF FF FF и т.д.)
Ежели по шагам выполняю программу со свеверменной подачей порций информации, то все отлично записывается, что я не так делаю?
Код вот такой:
Код while(1) { while(!(AT91F_US_RxReady(AT91C_BASE_US1))); AT91F_Flash_Write(testAdr, 256, buff_rx); COM1->US_RPR = (unsigned int)&buff_rx[0]; COM1->US_RCR = 256; testAdr += 0x100; } [size="2"][/size]
[size="2"]AT91F_Flash_Write - процедура записи во flash: - дизактивация прерываний - запись во flash - активация прерываний
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|