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

jcxz

Свой
  • Постов

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

  • Посещение

  • Победитель дней

    34

Весь контент jcxz


  1. Можно приоткрыть завесу тайны по данным 2-м пунктам?
  2. Во-втором случае будет простаивать как минимум в 2 раза большее кол-во памяти. Все кучефилы почему-то забывают об элементарной вещи, которая сводит на нет все +-ы кучи в embedded: если к примеру 2 потока используют периодически каких-то 2 блока памяти и зависимость во времени этих использований невозможно детерминировать и возможны моменты одновременного использования (т.е. - невозможно поместить эти 2 блока в union static), то они совершенно забывают, что если выделять эти блоки на куче, то тоже будут моменты одновременного использования, соответственно - объём памяти в куче должен быть равен не менее чем сумме размеров блоков (а в реальности - более из-за заголовков). Поэтому в типичном эмбеддед-приложении где нет запускаемых пользователем задач (которым при нехватке памяти можно отказать в запуске) или если нет таких потоков, выполнение которых можно остановить без ущерба функционированию системе при нехватке памяти, использование кучи не приводит к уменьшению требований по памяти, а наоборот - увеличивает требования к памяти + приводит к проблемам фрагментации. Поэтому обычное static-размещение + union для использований неперекрывающихся по времени, однозначно рулит. Поймите-же эту простую мысль, кучефилы, и творения ваши станут чуть менее глючными!!! :)
  3. Проще наложить одно единственное обязательство - не использовать кучу.
  4. TiWi-R2 (WL1271)

    Если-б вы просто тупо пощёлкали ссылки дальше, то поняли-бы что инфы реально нет ;) Юзермануал на WL1271 дают под NDA.
  5. Смотрим на название форума :) В ARM все 8-/16-/32-разрядные команды сохранения атомарны. Ну если только преднамеренно не разместить их невыровненными...
  6. Только когда пишет один процессор, а читает - другой, тут запрет прерываний не спасёт ;)
  7. Разруливается это двумя индексами - у каждого процесса - свой. Вот типичная реализация (проанализируйте методы read() и write()): class clas { volatile size_t rpos, wpos; u8 buf[N + 1]; public: size_t write(int); int read(); clas() { rpos = wpos = 0; } } int clas::read() //если нет данных - возвращает отрицательное { int i; size_t j = rpos; if (i = j - wpos) { i = buf[j] + 1; rpos = ((j) ? j: ncell(buf)) - 1; } return i - 1; } size_t clas::write(int c) //если не удалось записать (буфер полон) возвращает != 0 { size_t i, i1, i2; if (!(i1 = i2 = wpos)) i1 = ncell(buf); if (i = (--i1 - rpos)) { buf[i2] = c; wpos = i1; } return i; } #define ncell(m) (sizeof(m) / sizeof((m)[0]))
  8. Зачем???? И какие данные "общие"?
  9. Читайте внимательнее:
  10. Зачем же делать такое кривое FIFO??? :crying: Если иметь прямые руки и писать FIFO правильно - не нужно! :) Обычная реализация FIFO для межпроцессного (и даже - межпроцессорного взаимодействия): Два индекса (у каждого процесса свой). Каждый процесс (или ISR) модифицирует только свой индекс, чужой индекс он может только читать. Один процесс - только пишет в FIFO, другой - только читает. Каждый процесс двигает свой индекс записывая или читая в FIFO до тех пор, пока не упрётся в чужой индекс (что является признаком опустошения/заполнения FIFO). Минус такой реализации - реальная ёмкость FIFO на 1 элемент меньше выделенного для него буфера. Если элементы - байты - это ерунда.
  11. Корректный механизм в случае работы с UART через кольцевые буфера - вообще не запрещать прерывания. Зачем их запрещать если в кольцевой RX-буфер только один писатель - ISR, а в кольцевой TX-буфер - пишет только фоновый процесс?
  12. Википедия это конечно АВТОРИТЕТ! Любой TAutomatic знает :w00t:
  13. Меня умолять не надо - Вы почитайте описание на любой компоновщик. Я вам вроде ясные примеры привёл. Ничто не мешает компоновщику раскидать одноимённые входные секции (к примеру - секции .bss) по разным регионам памяти при наличии соответствующего ключа в конфигурации. Вы сами-то хотя-бы раз заглядывали в ассемблерные листинги после компилятора? Поинтересуйтесь вместо того чтобы писать тут ерунду.
  14. Позвольте встрять? ;) Кроме внутреннего ОЗУ, к контроллеру может быть подцеплено внешнее, с другим временем доступа. Даже если есть только внутреннее, то в некоторых процессорах есть разные RAM с разным быстродействием, расположенные на разных шинах. Или, к примеру: внутреннее ОЗУ разбито на банки (непрерывно расположенные в адресном пространстве), и одна из переменных - в одном банке, другая - в другом, а во второй банк как раз идёт интенсивное DMA (с приоритетом контроллера DMA) - здесь разница во времени доступа может быть ОЧЕНЬ большой. Даже если банки ОЗУ в несмежных областях - линкер (при соотв. опциях) может разбить выходные секции на неск. несмежных областей. Для каких-то областей может быть включено/выключено кеширование. Или (типичная оптимизация IAR for ARM): функция работает с неск. статическими переменными - IAR заносит в некий базовый регистр указатель на область памяти, которая включает большую часть этих переменных и адресует их через этот базовый + смещение, а одна переменная - далеко от остальных, разрядности смещения не хватает и для обращения к ней компилятору приходится вставлять доп. инструкции загрузки адреса этой переменной в регистр - соответственно доступ к этой переменной будет дольше. Перетасовка переменных оптимизатором - это большой гуд. ПО не должно привязываться к взаимному расположению переменных (конечно это не касается внутри структур).
  15. Неверно, ибо во флеш в общем случае пишется > одного сегмента. Сначала - надо определить порядок размещения входных сегментов во флеш, в конец пристроить определённый сегмент, его и смотреть. Я делаю так (*.icf): define block IMAGE_HEAD with fixed order { section .intvec, section .checksum, section .imagesize, section .intvecTail }; place in FLASH_region { ro, first block IMAGE_HEAD, last section .codetail }; (говорит - поместить во FLASH_region все readonly сегменты, первым - блок IMAGE_HEAD в котором у меня и сохраняется CRC) В сегменте .codetail определяю одну единственную переменную (*.asm): PUBLIC __codetail SECTION .codetail:CONST:NOROOT(2) __codetail DC32 0xAAAAAAAA её потом и использую как конец проги (не забывая добавить её в исключения линкёру, чтоб он не выкидывал её из выходного файла). Да - и в IAR есть возможность встроенной генерации CRC, что и использую.
  16. Аллокатор для Cortex-M3

    А зачем? Или вы про вызов конструкторов классов для буфера? Но что мешает явно его вызвать: char buf[N]; new (buf) ClassName(...); ClassName *p = (ClassName *)buf; ...
  17. Аллокатор для Cortex-M3

    Раз у вас не хватает памяти чтобы распределить её в виде static или на стеке для всех потоков, значит возможна ситуация (и даже с большей вероятностью), когда много потоков запросит больше памяти чем есть. С наличием служебных полей управления блоками в heap и фрагментации это даже более вероятно, чем при static размещении. Что ваша система должна делать при этом? Выдать отказ потоку (но значит алгоритм всех потоков должен рассчитывать, что может быть получен отказ в памяти)? Или приостановить выполнение потока (но может случиться dead-lock)? Я полностью согласен с Forger - делаю так же - стараюсь обходиться static. Если невозможно - использую динамическое выделение блоков фиксированной длины. Даже в довольно сложных проектах с многими потоками нигде не использую стандартный heap. Также помогает знание алгоритма работы потоков: где-то можно использовать union если нет одновременного использования памяти, где-то можно ставить семафоры на функции использующие большие блоки статической памяти и т.п.
  18. Это как у меня "не так" работает?? То что я вам привёл - это выдрано из рабочего ПО, которое вполне нормально работает. Часть - с DMA, часть - без. 16-битное - для оптимизации и для того, чтобы не запрещать прерывания на время нескольких операций записи в ssp->DR (у меня сигнал CS формируется аппаратно SSP). Цикл там только для случая, если флешка занята предыдущей операцией, если нет - проходит его в один проход. FIFO - это не причина для того чтобы не давать доступа к одному байту, оно нисколько не мешает. Это у вас там каша какая-то. aaarrr вам правильно написал - не надо лезть отладчиком в работающие регистры SSP. Чтение JTAG - то же самое, что чтение CPU.
  19. Не очень понятно в чём проблема? Работаю именно с этой AT45DB321 и с LPC1788 и ранее - с LPC2378 через SSP без проблем. Как с DMA, так и без. На SCLK==30МГц. Статус - читается только один байт. enum {CDF_STATUS = 0xD7}; //чтение регистра статуса //Возвращает статус static u32 WaitRDY(int hold = 0) { u32 i, j; volatile HwRegsSSP *ssp = &concatAB(SSP, nSSP_dflash); ssp->CR[0] = 15 | B6 | B7; ssp->CR[1] = B1; while (1) { ssp->DR = CDF_STATUS << 8; while (ssp->SR & B4); if ((i = ssp->DR) & B7) break; if (!hold) PostDF(); OSTimeDly(ms2tkt(2)); if (!hold) PendDF(); } ssp->CR[1] = 0; j = i & 0x3D; if (j != 0x2C && j != 0x34) trap(TRAP_DFLASH); return i; } void InitSSP(SspCtl *p, volatile HwRegsSSP *ssp, u32 cpsr) { ssp->IMSC = ssp->CR[1] = 0; ssp->CPSR = cpsr; ssp->DMACR = 0; while (ssp->SR & B2) { u32 i = ssp->DR; } p->mbox = MboxCreate(); SemPend(p->sem = SemCreate()); //блокируем до выполнения функции, конфигурирующей устройство }
  20. RL-ARM и bootloader

    Значит у вас не работает запуск рабочего ПО и при включении питания, а не только при ресете из него. Значит - надо вначале добиться этого, а потом сброс через сторожевик сделает его подобным PowerOn. "Как положить куда нужно" описано в командном файле компоновщика (в IAR это - *.icf)
  21. Всё-таки уникальный ID (уникальный внутри данного типа CPU) проще сделать, чем МАС - который уникальный среди всего множества всех устройств. Ладно - буду искать ещё. Или придётся извращаться - генерить свой уникальный ID на основе текущей даты/времени во время прошивки - благо шиться все будут в одном месте. Мне-то нужно для serial number в USB-дескрипторе - чтобы если 2 экземпляра устройства подключено к хосту - они различались. PS: Когда делали схему - нашёл в даташите этот DieID, вспомнил что в 5502 он был уникальным, а возможности проверить - не было. Вот на него и заложился. Иначе бы поставил SPI EEPROM с таким ID, но уже поздно :(
  22. По-моему для реализации SPI на McBSP/McASP вполне достаточно прочитать даташит на соотв. интерфейс, там всё доходчиво у TI. Вопрос к Вам, 'SAURIS GmbH', как к реально грамотному специалисту по процессорам TI - известен Вам в OMAP ядрах (конкретно - L137/L138) какой-либо уникальный идентификатор (уникальный для данного экземпляра, а не типа процессора)? В C5502 был такой: _CHIP_DIEIDH_ADDR (0x3800u) _CHIP_DIEIDL_ADDR (0x3802u) но в L137 регистр с подобный названием (SYSCFG.DIEIDR) не является таковым :( Или может такой ID есть в ROM ARM или ROM DSP?
×
×
  • Создать...