vmp 0 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Тогда получается, что TLB нужно хранить в SDRAM? И какие в этом проблемы? В моем примере так и сделано. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба И какие в этом проблемы? В моем примере так и сделано. Единственное, надо чтобы TLB лежала в некешеруемой области sdram. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 28 декабря, 2010 Опубликовано 28 декабря, 2010 (изменено) · Жалоба И какие в этом проблемы? Да проблем с этим нет. Вы не могли бы мне объяснить назначения доменов и соответственно битов AP? Вот привожу, что у меня получилось: Небольшие уточнения, правильно ли я понимаю: TLB располагаем в конце SDRAM, основную программу вначале (я для кэшируемой области памяти выделил первые 32 Мб), инициализируем ее как Write-Back, переферию делаем некэшируемой. Все, TLB готов! Если я хочу задать переменную в некэшируемой области памяти, то беру адрес, для которого TLB = 0, ну например 0x2350 0000. Тогда объявляем указатель: unsigned int *variable = (unsigned int *) (0x2350 0000); variable = 1234; // присваевыем, как пример, число переменной P.S. SII, спасибо Вам за ссылку! Изменено 28 декабря, 2010 пользователем ZED Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vmp 0 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Да проблем с этим нет. Вы не могли бы мне объяснить назначения доменов и соответственно битов AP? Это для защиты памяти при многозадачной работе в общем адресном пространстве. Типа каждой задаче - свой домен, чужие объявляем недоступными. Если я хочу задать переменную в некэшируемой области памяти, то беру адрес, для которого TLB = 0, ну например 0x2350 0000. Тогда объявляем указатель: unsigned int *variable = (unsigned int *) (0x2350 0000); // [b]Забыта *[/b] [b]*[/b]variable = 1234; // присваевыем, как пример, число переменной Я бы порекомендовал использовать возможности компилятора: #pragma location="NO_CACHE" unsigned int variable; variable = 1234; // А вот тут без звездочки В файле конфигурации линкера надо объявить секцию NO_CACHE и разместить ее в соответствующих адресах. В этом случае можно будет достаточно просто объявлять множество таких переменных, не занимаясь ручным заданием адресов Кстати, даже первый вариант можно описать в виде: #define variable (*(unsigned int *) (0x2350 0000)) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DpInRock 0 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Чисто совет. Кэш - отличная штука. Ускоряет так нормально. И если не мудрить, то просто работаешь как обычно. Кэшируемая или не кэшеруемая память - это важно лишь в очень специфических случаях. В обычной жизни такие случаи не встречаются. И еще не имеет особого смысла, особенно для 9260 кэшировать СРАМ. Ибо врядли вы там будете прямой доступ к памяти организовывать, а быстродействие кэша и СРАМ одинаковое. (Кэш срам полезен, когда в ней не только программа работает, но и область прямого доступа есть. Тогда программа работаетв кэше, а память свободна для DMA). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Единственное, надо чтобы TLB лежала в некешеруемой области sdram. Ни малейшей необходимости в этом нет. P.S. TLB = Translation Lookaside Buffer, а таблица называется Translation Table. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Блин код забыл прикрепить: unsigned int AT91F_ARM_ReadControl() { register unsigned int ctl; ctl = __MRC(15, 0, 1, 0, 0); return ctl; } void AT91F_ARM_WriteControl(unsigned int ctl) { __MCR(15, 0, ctl, 1, 0, 0); } void AT91F_ARM_WriteTTB(unsigned int ttb) { __MCR(15, 0, ttb, 2, 0, 0); } void AT91F_ARM_WriteDomain(unsigned int domain) { __MCR(15, 0, domain, 3, 0, 0); } //----------------------------------------------------------------------------- // Размер страницы = 4 Kб (0x1000) // Раскладка по памяти: // 0000 0000 - Boot Memory // 0010 0000 - ROM, не используется (32 Кб) // 0020 0000 - SRAM0 (4 Кб) // 0030 0000 - SRAM1 (4 Кб) // 0050 0000 - UHP (16 Кб) // 2000 0000 - SDRAM (32 Mб) // 4000 0000 - NAND DATA // 4020 0000 - NAND ADDR // 4040 0000 - NAND CMD // FFF0 0000 - Периферия //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Описания секций: // [1..0] = "01"; // 2 - B - Bufferable; // 3 - C - Cacheable; // 4 - '1'; // [8..5] - Domain = "1111"; // 9 = '0'; // [11..10] - AP; // [19..12] = "00000000" // [31..20] - Базовый адрес секции // Биты AP // 01 - Нет доступа (No Access) // 10 - Только чтение (Read-only) // 11 - Чтение/Запись (Read/write) // Биты C и B: // 0 0 - Не Кэшируемая, Не Буферизируемая // 0 1 - Не Кэшируемая, Буферизируемая // 1 0 - Write-Trough-кеш // 1 1 - Write-Back-кеш //----------------------------------------------------------------------------- #define TLB_ADDR 0x2F000000 // Базовый адрес расположения TLB в памяти #define TLB_NCNB 0xDF2 // Noncachable, Nonbufferable 11 0 1111 1 00 10 #define TLB_WT 0xDFA // Write-through 11 0 1111 1 10 10 #define TLB_WB 0xDFE // Write-back 11 0 1111 1 11 10 // Инициализация MMU: void AT91F_InitMMU(void) { // TLB располагается в SDRAM unsigned int *TLB = (unsigned int *) (TLB_ADDR); unsigned int i, ctl; // Инициализация TTB: AT91F_ARM_WriteTTB(TLB_ADDR); // Записать начальный адрес расположения TTB (CP15 c2) AT91F_ARM_WriteDomain(0xFFFFFFFF); // Domain Access Control Register (CP15 c3) // Очистка TLB: for (i = 0; i < 4096; ++i) TLB[i] = 0; // После Reamp по адресу 0x00000000 расположена SRAM0: TLB[0x000] = 0x00000000 | TLB_WB; // После Reamp по адресу 0x00100000 расположена ROM: TLB[0x001] = 0x00100000 | TLB_NCNB; // SRAM1: TLB[0x003] = 0x00300000 | TLB_WB; // UHP: TLB[0x005] = 0x00500000 | TLB_WB; // Код основной программы, расположенный в SDRAM (32 Мб): for (i = 0x200; i < 0x200 + 31; i++){ TLB[i] = (i << 20) | TLB_WB; } // Переферия: TLB[0xFFF] = 0xFFF00000 | TLB_NCNB //Разрешить MMU ctl = AT91F_ARM_ReadControl(); ctl |= (1 << 0); AT91F_ARM_WriteControl(ctl); //Разрешить I-Cache ctl = AT91F_ARM_ReadControl(); ctl |= (1 << 12); AT91F_ARM_WriteControl(ctl); //Разрешить D-Cache ctl = AT91F_ARM_ReadControl(); ctl |= (1 << 2); AT91F_ARM_WriteControl(ctl); } И еще не имеет особого смысла, особенно для 9260 кэшировать СРАМ Т.е. эта строчка лишьняя: // После Reamp по адресу 0x00000000 расположена SRAM0: TLB[0x000] = 0x00000000 | TLB_WB; Чисто совет. Кэш - отличная штука. Ускоряет так нормально. И если не мудрить, то просто работаешь как обычно. Кэшируемая или не кэшеруемая память - это важно лишь в очень специфических случаях. В обычной жизни такие случаи не встречаются. Вот видимо у меня такой случай. Я все это делаю, чтобы запустить EMAC на вышеупомянутом контроллере. И вот в теме, которую я открыл, чтобы с ним разобраться EMAC AT91SAM9260. Так вот в этой теме мне сказали, цитирую: дескрипторы должны быть в не кешируемой области. Вот поэтому я так все дотошно и спрашиваю, хочу разобраться. Просто еще несколько месяцев назад я вообще не знал что такое ARM процессоры, IAR, J-Link и т.д. Не говоря уже о кэшах, MMU и всего подобного. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DpInRock 0 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Ну и что что в некэшируемой. Ставите нужный битик в описании нужной страницы и все. И она уже некэшируемая. Всякие там буфера прямого доступа, оне приравниваются по своему сволочизму к аппаратным регистрам. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба To ZED: У Atmel'a, чтобы не было проблем с когерентностью буферов и DMA надо просто все буфера для DMA объявить в некешируемой области. Для этого прислушайтесь к совету vmp. В чистом виде это относится и к EMAC (там еще особые требования по выравниванию адресов таблиц). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Вообще, лучше все же применять творческий подход, а не рубить сразу - тут кэшируем, а тут не кэшируем. Во многих случаях может быть весьма уместен режим write-through (например, у framebuffer'а экрана), построчная или полная инвалидизация кэша (как раз при работе с буферами ПДП), залочка части программы/данных для критичных участков и т.п. Понятно, что сразу подобные упражнения могут и не понадобиться, но списывать их со счетов, один раз все настроив и забыв, совсем не стоит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 29 декабря, 2010 Опубликовано 29 декабря, 2010 · Жалоба Спасибо Вам большое за советы и помощь! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 29 декабря, 2010 Опубликовано 29 декабря, 2010 · Жалоба Теперь возникли проблемы с PLL. Хотел протестировать работу MMU, для этого написал код дрыгания ножкой. В этом коде есть функция инициализации PLL: // Частота медленного RC-генератора SLCK 32.768 кГц. Период 1/32768 = 30.51 мкс // Максимальное время запуска основоного генератора: 75 мкс // Время запуска основного генератора:8 * OSCOUNT(=16) * 30.51 мкс = 3.9 мс // Запуск основного генератора: AT91C_BASE_PMC->PMC_MOR = (AT91C_CKGR_OSCOUNT & (0x40 << 8)) | AT91C_CKGR_MOSCEN; // Ждать пока пройдет время запуска: while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS)); // Переключение блока задающей частоты на основную тактовую частоту AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_MAIN_CLK; // Настройка PLL на частоту 192 МГц: AT91C_BASE_PMC->PMC_PLLAR = ( AT91C_CKGR_SRCA // 29 бит = 1 | (0x2 << 14) // OUTA = 2 | (0xBF << 8) // PLLACOUNT = 191 | (AT91C_CKGR_MULA & (0x7C << 16)) // MULA = 124 | (AT91C_CKGR_DIVA & 12)); // DIVA = 12 // Ждать пока пройдет время запуска: while(!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCKA)); // Выбор задающей частоты и тактовой частоты процессора: // Предделитель тактовой частоты PRES = 1, Предделитель задающей частоты MDIV = 2. AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK | AT91C_PMC_MDIV_1; // Ждать пока пройдет время запуска: while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)); // В качестве основной частоты использовать частоту PLL: AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLLA_CLK; // Ждать пока пройдет время запуска: while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)); Проблема в том, что на строчке: AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLLA_CLK; IAR выдает следующее: Wed Dec 01 12:30:11 2010: The stack 'CSTACK' is filled to 99% (4087 bytes used out of 4096). The warning threshold is set to 90.% Wed Dec 01 12:30:11 2010: The stack 'IRQ_STACK' is filled to 95% (92 bytes used out of 96). The warning threshold is set to 90.% Полазил по форуму, там написано, что все дело в REMAP. Пробовал делать REMAP вручную: AT91C_BASE_MATRIX->MATRIX_MRCR = AT91C_MATRIX_RCA926I | AT91C_MATRIX_RCA926D; Все тоже самое. Помогите разобраться. Кстати еще вопрос, с какой примерно частотой у меня должна будет дрыгаться ножка при включенном MMU и Кэшах? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DpInRock 0 29 декабря, 2010 Опубликовано 29 декабря, 2010 · Жалоба В жизни не получал таких варнингов от ИАР. Скорее всего потому, что стараюсь не передавать слишком много параметров в функции. И слежу за вложенностью... Ремап никак не связан с варнингами. (Или это симулятор-отладчик такое выдает?) Ремап надо делать или не делать в зависимости от надобности. B __iar_program_start ; это должна быть первой строчкой вашего стартапа. __iar_program_start: /********************************************************************** * ?CSTARTUP * * Execution starts here. * After a reset, the mode is ARM, Supervisor, interrupts disabled. */ ?cstartup: tst PC, #0x300000; test for current map beq _after_remap; mvn r0, #0xFF ;remap here bic r0,r0, #0x1100 mov r1, #0x03 str r1, [r0, #+0] _after_remap: В этом коде проверяется где нах. программа и делается ремап если надо. Ассемблера АРМ не знаю, делал наугад. Но работает железно. ---- По поводу ковыряния с кэшем - согласен с aaarrr - но только все делать последовательно. Сначала что по проще (написать и забыть), а уж потом, когда придет понимание процессов с одной стороны и нужда - с другой - то можно и потренироваться с управлением кэшем. Про ножку. Смотря откуда код исполняется... В даташите гляньте - там должна быть указана частота тактирования портов. Вот больше нее - никак. (Если порты тут тактируются - не помню). Лучше проверять по DBGU. Типа, работает - не работает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 29 декабря, 2010 Опубликовано 29 декабря, 2010 · Жалоба Ремап никак не связан с варнингами. (Или это симулятор-отладчик такое выдает?) Именно он, когда дохожу до вышеуказанной строчки. Скорее всего потому, что стараюсь не передавать слишком много параметров в функции. Так функция и не содержит никаких параметров: void Init_CLK(void). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DpInRock 0 29 декабря, 2010 Опубликовано 29 декабря, 2010 · Жалоба Симуляторы и отладчики - зло. Вообще тогда смотрите размер стека. Если по умолчанию, то там совсем маленькие стеки (0x10). А если разрешены вложенные прерывания, то совсем будет плохо.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться