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

Supernaut

Участник
  • Постов

    31
  • Зарегистрирован

  • Посещение

Репутация

0 Обычный

Информация о Supernaut

  • Звание
    Участник
    Участник
  1. Скорость при чтении не зависит от write-back/write-through - ведь содержимое памяти не изменяется. Другое дело при записи - write-back изменяет только содержимое кэша и ставит пометку об изменении, так что, по идее, должно быть быстрее, чем write-through.
  2. Не могли бы вы выложить фрагмент с настройками кэша и передачей управления в SDRAM? Насколько я понимаю, после ресета внутренняя память L1 инструкций и данных настроена как SRAM (т. е. кэширование выключено). При этом лоадер выполняется в SRAM инструкций (L1 instruction memory). В Blackfin Processor Programming Reference сказано, что в этом режиме при попытке выполнить инструкцию из - пустой области инструкций L1, - области данных L1, - области MMR вырабатывается исключение. Я пробовал включить кэширование (пример взял из u-boot, там выполняются настройки CPLB и включаются кэши) - но после выполнения этих ф-ций перестали выполняться следующие за ними инструкции (вывод содержимого регистров IMEM_CONTROL, DMEM_CONTROL и переход в SDRAM). Помогите плиз, ибо я в отчаянии!
  3. Нет, основная программа - это обычный бинарный файл, не ldr. По идее, его нужно просто положить в SDRAM и передать ему управление. Можно ведь и основную программу также писать в spi-флэш. Тогда еще и место на плате сэкономите :) Ставите BMODE на загрузку по spi и вперед...
  4. Можно посмотреть LdrViewer-ом структуру вашего бутлоадера - там видно, какой диапазон адресов в SDRAM занят под лоадер. И скопировать рабочую программу в заведомо свободную область памяти. А вообще бутлоадер удобно делать небольшой програмкой, целиком влезающей в кэш. SDRAM в таком случае останется полностью в распоряжении основной программы.
  5. Самое простое: 1. Пишете бутлоадер, с помощью bfin-elf-ldr (под Линукс) или VisualDSP получаете файлик в формате .ldr 2. Любым способом записываете этот лоадер в spi-флэш. 3. Бутлоадер стартует, принимает рабочую программу по UART и кладет ее в SDRAM по нужному адресу (+ если надо, и в параллельную флэш). 4. Передаете управление рабочей программе в SDRAM. Единственное, с чем пока еще сам не разобрался - п 4. Видимо, как-то надо специально разрешить блэкфину выбирать инструкции из SDRAM. Простой джамп на начало основной программы в SDRAM ни к чему не приводит.
  6. Извините, что встреваю, но имею очень похожую проблему. Не получается прыгнуть в SDRAM - по окончании закачки рабочей программы в SDRAM по адресу 0х1000 вот это __asm__("P0.H = 0x0000;"); __asm__("P0.L = 0x1000;"); __asm__("JUMP (P0);"); приводит к зависанию проца (bf537 в моем случае). Файл пишется в SDRAM корректно, проверял. Чего не хватает для счастья? :)
  7. Я должен несколько пояснить. Код для SDRAM - это у меня просто бинарный файл, не .ldr. Этот файл - u-boot.bin - я обычно записываю в параллельную флэш при работе в bypass mode. При старте этот код начинает выполняться из флэш. Далее, средствами этого у-бута я могу положить по любому адресу в оперативке этот же самый u-boot.bin: tftp 0x1000 u-boot.bin Далее, я могу запустить его на выполнение: go 0x1000 Все работает. Смысл же моих телодвижений - другим способом положить u-boot.bin в оперативку по адресу 0х1000 и передать ему управление. Действия, описанные в первом сообщении, привели к зависанию процессора. Что я делаю не так? Ведь, по идее, надо просто "прыгнуть" на 0х1000? Или что-то еще?
  8. Добрый день. Собственно задача: пишу самодельный загрузчик для BF537, принимающий по X-modem программу (а именно, u-boot.bin) и кладущий в SDRAM (в будущем - в SPI-flash). Сам загрузчик - програмка в формате .ldr, выполняющийся во внутреннем кэше процессора. После процесса загрузки u-boot в SDRAM передаю ему управление вот так (у-бут расположен с адреса 0х1000): __asm__("P0.H = 0x0000;"); __asm__("P0.L = 0x1000;"); __asm__("JUMP (P0);"); Не работает - процессор тупо виснет... Что SDRAM работает правильно - проверял простеньким самодельным тестиком (пишу = читаю); к тому же средствами у-бута проверял содержимое памяти с адреса 0х1000 после записи своим загрузчиком - оно такое же, как при закачке файла u-boot.bin по tftp. Как правильно заставить процессор выполнять инструкции из SDRAM? Подскажите, кто чем может... :)
  9. Глюки проявляются в том, что контроллер просто зависает! Т. е, не выходит из этой функции. И это при числе элементов уже порядка 3000. А уменя реальный массив из 30000 элементов! Насчет одинаковых элементов - их в моем массиве заведомо нет, все разные! Приведу для ясности кусок кода, может, кто-нибудь увидит ошибку. // формируем указатели на массив указателей на структуры типа Spl Spl **rec_ptr_array; // выделяем память под массив согласно кол-ву структкр - их может быть порядка 30.000 rec_ptr_array=new Spl *[N]; if(rec_ptr_array!=NULL) { // инициализируем массив указателей на структуры типа Spl for(k=0;k<N;k++) { rec_ptr_array[k]=(Spl *)(Start_addr+2*(offset+3*k)); } // включаем светодиод SetLED(TX, RED); // сортируем структуры в порядке возрастания значения одного из полей qsort((void *)rec_ptr_array[0], N, 6, spl_compare); // выключаем светодиод SetLED(TX, OFF); } И далее, функция сравнения двух элементов: int spl_compare(const void *a, const void *B) { Spl *pa=(Spl *)a, *pb=(Spl *)b; if(pa->Get_SN() > pb->Get_SN()) return 1; else if(pa->Get_SN() == pb->Get_SN()) return 0; else return -1; }
  10. Привет всем! Господа, программирующие на С/С++! Подскажите, каково максимальное число элементов для сортировки для функции qsort()? В хелпе вскользь намекается, что size_t - тип беззнаковое целое, т. е. занимает 4 байта (компилятор IAR, пишу под AT91... ARM). То есть, подразумевается довольно большое число сортируемых элементов? А у меня прога глючит при числе элементов уже более 1500... Для малых массивов данных - работает как часы! Или лучше писать свою функцию сортировки? Спасибо!
  11. Да, функция обработчика прерывания TC0_IRQ() упоминается в map файле, и именно ее адрес передается контроллеру прерываний: AIC_SVR4 = (unsigned int)(&TC0_IRQ). Попробовал прочитать его в обработчике прерываний. Результат тот же :( Я имел в виду, что выход из бесконечного цикла происходит не по окончании обработчика прерывания, а по срабатыванию сторожевого таймера - т. е. контроллер просто сбрасывается. Сброс же самого вачдога происходит непосредственно перед запуском таймера и входом в бесконечный цикл while(1). Победа!!! SpiritDance, Вы были правы!!! Действительно, надо было читать статусный регистр таймера в обработчике прерывания! Просто я купился на вот эту строчку в даташите: The interrupt handler must read the AIC_IVR as soon as possible. В общем, правильная функция обработчика прерывания выглядит так: __irq __arm void TC0_IRQ(void) { tmp = TC_SR0; tmp = 0xAABBCCDD; PIO_SODR=1<<4; delay(10); // Задержка 10 мкс PIO_CODR=1<<4; AIC_EOICR = 1; } Надеюсь, это кому-нибудь поможет. SpiritDance, огромное спасибо за живое обсуждение!!!
  12. Работают внешние прерывания IRQ0, IRQ1, IRQ2 (источники 16, 17, 18 соответственно). Правда, не в моей программе, а в другой, которую я взял как образец. Настройки для AIC там аналогичные. Честно говоря, я не большой специалист в программировании на С. Если имя функции является указателем на ее место в памяти - тогда да, Вы правы. Да, тот. Источник прерывания №4 - это 0-вой канал таймера. Неоднократно всё уже сверял с даташитом. Какой Вы имеете в виду статусный регистр - регистр таймера TC_SR0 или регистр контроллера прерываний AIC_ ISR? Если первый - то в этом нет смысла, т. к. в данном случае я знаю, что прерывание может произойти только по событию TC_CV=RC0. Если второе - зачем мне знать номер источника, вызвавшего прерывание, если я уже и так оказался в обработчике нужного прерывания? Может, я неверно рассуждаю, но, по крайней мере, в даташите я ничего не нашел про обязательное чтение статусного регистра. Насчет break все просто - если я пытаюсь выйти из цикла по условию tmp=0xCCAAABBB (запись этого числа должна происходить в обработчике прерывания), то просто происходит сброс контроллера по сторожевому таймеру. tmp объявлена как глобальная переменная, т. е., по идее, видна и из обработчика прерывания, и из основной программы... да и компилятор бы ругался, если с этим что не так... В общем, не знаю где копать...
  13. Да, разрешены - бит I в регистре cpsr прописывается =0 еще в загрузчике. После всех предварительных настроек загрузчик передает управление основной программе, кусок которой я привел.
  14. Привет всем! Кто-нибудь сталкивался с такой трудностью - не срабатывает прерывание от таймера, хотя само событие, по которому должно случиться прерывание - происходит? Таймер должен отмерять интервал времени 300 мкс для формирования манчестерского кода. Приведу кусок своей программы, может, кто-нибудь увидит ошибку: /* Настраиваем регистры контроллера прерываний */ AIC_IECR = (unsigned int)(1<<TC0IRQ); // бит TC0IRQ = 1 - разреш. прер. от таймера (канал 0) AIC_SMR4 = 0x00000007; // PRIOR = 111 - приоритет =7 - самый высший // SRCTYPE = 00 - по уровню AIC_SVR4 = (unsigned int)(&TC0_IRQ); // адрес обработчика прерывания таймера (канал 0) /* Настраиваем 0-й канал таймера */ TC_BCR=0x00000000; // SYNC=0 - 3 блока таймера работают независимо; TC_BMR=0x00000015; // TC0XC0S=01 \ // TC0XC1S=01 | запрещ. внеш. такт. сигналы для всех 3-х блоков // TC0XC2S=01 / TC_CCR0=0x00000001; // CLKEN=1 - разрешаем подачу тактовой частоты на канал 0 TC_CMR0=0x00008040; // TCCLKS=000 - такт. частота MCK/2=32,768 МГц // CLKI=0 - не инвертируем такт. частоту // BURST=00 - такт. частота - не управляется внешним сигналом // CPCSTOP=1 - останов такт. ч-ты когда достигнем значения RC0 // CPCDIS=0 - не запрещаем такт. ч-ту когда достигнем значения RC0 // EEVTEDG=00 // EEVT=00 // ENETRG=0 // CPCTRG=0 // WAVE=1 - waveform mode // остальные биты=0 - никакой внешней реакции на достижение RC0 TC_RC0 = T_300mks; // константа, соотв. 300 мкс при такт. ч-те =32,768 МГц TC_IER0=(unsigned int)(1<<CPCS); // CPCS=1 - прерывание по достижению значения RC0 /* Обработчик прерывания от таймера 300 мкс (канал 0). Для отладки - моргнуть светодиодом и записать некое число в регистр tmp */ __irq __arm void TC0_IRQ(void) { tmp = AIC_IVR; tmp = 0xAABBCCDD; PIO_SODR=1<<4; delay(10); // Задержка 10 мкс PIO_CODR=1<<4; AIC_EOICR = 1; } /* Основная программа */ ............................. /* Запускаем таймер и ждем пока пройдет 300 мкс */ TC_CCR0=(TC_CCR0 | 0x00000004); // SWTRG=1 - сброс таймера и подача такт. частоты while(1) { if( ((TC_SR0 >> CPCS) & 1) == 1 ) break; // if( tmp == 0xAABBCCDD ) { tmp=0; break; } } ........................... Если выхожу из бесконечного цикла по флагу CPCS в статусном регистре TC_SR0 - все в порядке, т. е. таймер работает правильно. Тем не менее, если заменить усл-е выхода из бесконечного цикла на закомментированное - программа не работает, т. е. обработчик прерывания не выполняется. Буду очень благодарен за советы и за любую помощь.
  15. alex-sss, загляните пожалуйста в личный почт. ящик - есть для Вас сообщение
×
×
  • Создать...