Перейти к содержанию
    

Проблемы с записью/считыванием во/из Flash

Проблема состоит в том, что по уарту приходят данные и записываются в буфер, который я пытаюсь записать во флеш и, соответственно, считать из флеша.

 

Так вот записываю я одни данные, а считываются другие, вернее, происходит какая-то странная подмена одних байтов другими. К примеру(все в шестнадцатиричном виде):

 

 

 

| Записываю | Считываю |

 

| 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.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

Бит-реверсия получается, однако...

А вы уверены что это ошибка во флеш, а не в УАРТе? Иначе говоря, УАРТ проверен, в нем есть уверенность?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ха! Действительно, как не заметил...

 

Если посылаю с компа на комп по КОМ-порту, то все корректно приходит, без реверсии... То же самое наблюдается и в ИАРе, когда пошагово выполняю, т.е. в RX-массиве оказываются верные 4-хбайтовые числа...

 

Получается, что меняются старшие и младшие биты местами... Вернее считывание числа из массива происходит наоборот... А как-нть этого можно избежать?

 

 

Edmundo, cпасибо за подсказку, буд дальше мучать :)

Изменено пользователем Redaer

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Получается, что меняются старшие и младшие биты местами... Вернее считывание числа из массива происходит наоборот... А как-нть этого можно избежать?

 

Edmundo, cпасибо за подсказку, буд дальше мучать :)

Интуитивно мне кажется, что при работе с флеш бит-реверсии получиться не может (справедливости ради скажу, что в SAM'ах флешку не щупал). А вот при работе с последовательными интерфейсами -- запросто :), сами понимаете.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я впринципе пишу также, у меня все нормально, не видно как тут идет прием из ком-порта ..... Я вобщем делаю так: у меня есть некий буфер на 200 байтов, по приходу разного количества байт я записываю их в этот буфер, а буфер потом во флэш. При включении контроллера я эти байты считываю из флэш в буфер .... И все вроде бы пока нормально, ошибок таких, как был записан или считан не верный байт, не было ..... Даже если приходит на ком-порт всего один байт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Получается, что меняются старшие и младшие биты местами... Вернее считывание числа из массива происходит наоборот... А как-нть этого можно избежать?

 

Edmundo, cпасибо за подсказку, буд дальше мучать :)

Интуитивно мне кажется, что при работе с флеш бит-реверсии получиться не может (справедливости ради скажу, что в SAM'ах флешку не щупал). А вот при работе с последовательными интерфейсами -- запросто :) , сами понимаете.

 

 

 

Ага, только если на КОМ посылается больше 1 байта, то он передает их в обратном порядке, т.е.: если посылать по кому 0x1234, то он отправит их как 0x3412, а никак не 0x589 -- проверял на арме

 

 

 

прием данных происходит так(не пинать :) , но дружеский подзатыльник можно :biggrin: )

 

 

        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;

 

 

 

Вот думаю, может в каком-нть месте произвести реверсию, к примеру, при отправке с компа на уарт арма?.. Есть смысл?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

если посылать по кому 0x1234, то он отправит их как 0x3412

Ну это наверное уже little endian имеет место быть.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Может быть...

В общем, просто реверс в проге, которая скидывает инфу с компа сделал. Вроде работает...

Но все равно интересно, че за глюк такой...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Может быть...

В общем, просто реверс в проге, которая скидывает инфу с компа сделал. Вроде работает...

Но все равно интересно, че за глюк такой...

Реверс байтов или битов?

 

Здесь необходимо разобраться в проблеме. Если реверс байтов, то посмотрите: не получается ли у вас где-то так, что вы оперируете массивом int'ов (или short'ов) в одном месте, а в другом -- массивом байтов. В этом случае надо четко представлять порядок байтов при расположении в памяти с учетом endian'а.

 

Если битов, то вероятно это неправильное направление передачи по последовательному интерфейсу (есть два варианта: MSB first и LSB first). Я в свое время делал бит-реверсию по алгоритму из книги Уорена мл. для передачи по SPI, так как там возможно лишь MSB first (в отличие от SSC, где порядок можно настроить). Как в УАРТе -- не знаю, не увлекался :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я в свое время делал бит-реверсию по алгоритму из книги Уорена

 

А что за алгоритм?

Случайно не так:

   BYTE b;
   b = ((b<<4) & 0xF0) | ((b>>4) & 0x0F);
   b = ((b<<2) & 0xCC) | ((b>>2) & 0x33);
   b = ((b<<1) & 0xAA) | ((b>>1) & 0x55);

 

Если нет то расскажите. :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А что за алгоритм?

Случайно не так:

   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;
}

Там можно код чуть соптимизировать, уменьшить число операций за счет констант, но меня по производительности устраивало, поэтому оставил форму как из книги :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я реверсию битов сделал

 

Вот ещё вопрос, когда, во флешь что-то пишешь, её нужно предварительно очистить(как я понял, забить 0xFF). Но во флеше, насколько я знаю, хранится таблица векторов прерываний, она не сотрется? И вообще, какой у нее адрес?

З.Ы. Начинаю писать с такого адреса 0x100000

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Посмотри внимательно, ты случайно не ставишь бит MSBF (16 бит) в регистре US_MR?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот ещё вопрос, когда, во флешь что-то пишешь, её нужно предварительно очистить(как я понял, забить 0xFF). Но во флеше, насколько я знаю, хранится таблица векторов прерываний, она не сотрется? И вообще, какой у нее адрес?

З.Ы. Начинаю писать с такого адреса 0x100000

Ну это уже вопросы к doc6175. А после внимательного прочтения сюда, если что не ясно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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]

 

 

AT91F_Flash_Write - процедура записи во flash:

 

- дизактивация прерываний

 

- запись во flash

 

- активация прерываний

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...