Polaris 0 23 сентября, 2009 Опубликовано 23 сентября, 2009 · Жалоба Добрый день! У меня в процессе освоения LPC2368 возник вопрос относительно понимания работы VIC. В качестве источников информации использую даташит с сайта NXP (LPC2364/2366/2368) и книгу The insider's guide to the NXP LPC2300/2400 based microcontrollers Тревора Мартина. Вот как происходит назначение процедуры обработки вектора прерывания по Мартину: /* Setup Timer Counter 0 Interrupt */ VICVectAddr4 = (unsigned)tc0_isr; VICVectCntl4 = 0x02 VICIntEnable = 1 << 4; С VICIntEnable все понятно, это подробно и четко прописано в даташите на контроллер, тут неоднозначностей нет. А вот с адресом не совсем понятно. В данном примере, случайно или нет, бит, взведенный в VICIntEnable, совпадает с номером регистра адреса. Но из текста (особенно в даташите скудно об этом написано), следует вроде бы, что никакой связи нет, регистры равноправны и опрашиваются последовательно. Или я неправильно понял? Потому что тот же Мартин некоторые примеры приводит с регистром адреса совершенно не совпадающим с нужным битом. У меня такие примеры не работали, пока я не приводил в соответствие бит, отвечающий за источник прерывания в VICIntEnable с номером регистра адреса. Сейчас у меня большая часть нужной периферии включилась в проект и успешно в нем трудится, но оставлять такой скользкий момент за плечами не хотелось бы. Пожалуйста, ткните меня в фразу из даташита, где это однозначно определяется! Спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 23 сентября, 2009 Опубликовано 23 сентября, 2009 · Жалоба С VICIntEnable все понятно, это подробно и четко прописано в даташите на контроллер, тут неоднозначностей нет. А вот с адресом не совсем понятно. В данном примере, случайно или нет, бит, взведенный в VICIntEnable, совпадает с номером регистра адреса. Но из текста (особенно в даташите скудно об этом написано), следует вроде бы, что никакой связи нет, регистры равноправны и опрашиваются последовательно. Или я неправильно понял? Не понимаю, если честно, Ваших затруднений - как иначе контроллеру знать, какой VICVectAddr использовать? Возможно, путаница происходит из-за того, что раньше NXP использовали контроллер PL190, у которого каждый источник можно было привязать к любой паре Addr/Cntl, в то время как на новых кристаллах ставят PL192. А примеры просто забыли поправить. Полную документацию на них можно найти здесь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 23 сентября, 2009 Опубликовано 23 сентября, 2009 · Жалоба Вообще-то в нормальной технической литературе описание общих принципов работы ядра и периферии семейства МК размещают в User's Manual. А в datasheet находится уточняющая информация о конкретных характеристиках одного или нескольких кристаллов из семейства. Так что вам нужно видимо UM10211 LPC23XX User manual читать, а не только datasheet. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 23 сентября, 2009 Опубликовано 23 сентября, 2009 · Жалоба Да нет, там и в мануале описание VIC урезано до предела, т.к. это стандартное решение от ARM. Правда, могли бы и написать, куда обращаться за расширенной информацией. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Polaris 0 23 сентября, 2009 Опубликовано 23 сентября, 2009 · Жалоба Не понимаю, если честно, Ваших затруднений - как иначе контроллеру знать, какой VICVectAddr использовать? Возможно, путаница происходит из-за того, что раньше NXP использовали контроллер PL190, у которого каждый источник можно было привязать к любой паре Addr/Cntl, в то время как на новых кристаллах ставят PL192. А примеры просто забыли поправить. Полную документацию на них можно найти здесь. Вот я тоже так подумал, откуда ему знать, поэтому и поправил сам везде. А примеры, наверное, действительно забыли исправить, что не есть хорошо в книге для начинающих. Если все так обстоит, то вопрос можно закрывать - разобрался :) Спасибо за ответ!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 24 сентября, 2009 Опубликовано 24 сентября, 2009 (изменено) · Жалоба Если все так обстоит Можете точно убедиться - прочитать user manual на какой-нибудь процессор из старой серии (например, LPC2138) и сравнить раздел VIC ;) Инициализация в таком случае будет выглядеть так (LPC2138, EINT2): VICIntSelect &= ~BIT(16); VICVectAddr1 = (void*)BusyHandler; VICVectCntl1 = 0x20 | 16; VICIntEnable = BIT(16); Похоже? :) Изменено 24 сентября, 2009 пользователем esaulenka Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Polaris 0 24 сентября, 2009 Опубликовано 24 сентября, 2009 · Жалоба Можете точно убедиться - прочитать user manual на какой-нибудь процессор из старой серии (например, LPC2138) и сравнить раздел VIC ;) Инициализация в таком случае будет выглядеть так (LPC2138, EINT2): VICIntSelect &= ~BIT(16); VICVectAddr1 = (void*)BusyHandler; VICVectCntl1 = 0x20 | 16; VICIntEnable = BIT(16); Похоже? :) Очень похоже!!! Значит, Мартин проглядел этот момент, адаптируя книгу под LPC23xx/24xx. Спасибо за разъяснения! Вообще-то в нормальной технической литературе описание общих принципов работы ядра и периферии семейства МК размещают в User's Manual. А в datasheet находится уточняющая информация о конкретных характеристиках одного или нескольких кристаллов из семейства. Так что вам нужно видимо UM10211 LPC23XX User manual читать, а не только datasheet. Я извиняюсь за неточность в определениях, но под даташитом подразумевал именно User manual, потому что сколько-нибудь достойной информации кроме обзора возможностей в даташите вообще нет, и рассматривать его в качестве руководства по контроллеру вряд ли стоит. Кстати, такой же момент есть и в подборке code bundle for lpc23xx/lpc24xx с сайта NXP. Там в файле irq.c, где собраны макросы для работы с прерываниями, на которые ссылаются практически все примеры из набора, в функции install_irq есть следующий кусок: ... /* find first un-assigned VIC address for the handler */ vect_addr = (DWORD *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + IntNumber*4); vect_prio = (DWORD *)(VIC_BASE_ADDR + VECT_PRIO_INDEX + IntNumber*4); *vect_addr = (DWORD)HandlerAddr; /* set interrupt vector */ *vect_prio = Priority; VICIntEnable = 1 << IntNumber; /* Enable Interrupt */ return( TRUE ); ... Видимо, комментарий по поводу нахождения первого неназначенного адреса из той же оперы. Я лично никакой логической связи между ним и последующим текстом не увидел, а вот сомнения посеялись :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 24 сентября, 2009 Опубликовано 24 сентября, 2009 · Жалоба Ну дык copy-paste все любят, а вот комментарии переделывать лень. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 24 сентября, 2009 Опубликовано 24 сентября, 2009 · Жалоба Там в файле irq.c, где собраны макросы для работы с прерываниями, на которые ссылаются практически все примеры из набора, в функции install_irq есть следующий кусок: ... /* find first un-assigned VIC address for the handler */ vect_addr = (DWORD *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + IntNumber*4); vect_prio = (DWORD *)(VIC_BASE_ADDR + VECT_PRIO_INDEX + IntNumber*4); *vect_addr = (DWORD)HandlerAddr; /* set interrupt vector */ *vect_prio = Priority; VICIntEnable = 1 << IntNumber; /* Enable Interrupt */ Да тут и исходники уму не растяжимы :(, по-человечески это так примерно выглядит: *(ulong *)(&VICVectAddr0 + IntNumber) = (ulong)HandlerAddr; *(ulong *)(&VICVectPriority0 + IntNumber) = Priority; VICIntEnable = (1<<IntNumber); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Andy_Mozzhevilov 0 25 сентября, 2009 Опубликовано 25 сентября, 2009 · Жалоба Да тут и исходники уму не растяжимы :(, по-человечески это так примерно выглядит: Мой вариант работы с VIC vic.zip Использование выглядит примерно так: VIC::set_irq(VIC::TIMER2, sIsrT2); VIC::enable_irq(VIC::TIMER2); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 25 сентября, 2009 Опубликовано 25 сентября, 2009 · Жалоба Мой вариант... Использование модифицированных относительно мануала имен портов точно не есть хорошо... Остальное, остальное, типа многочисленных оберток на элементарные действия, "на любителя". Лично я не любитель такой навороченности на ровном месте. Хватает: int install_irq( bint inum, void *handler, bint priority, bint irq_enable ) { if( ( inum >= 32 )||( (priority ) >= VIC_SIZE ) ) return( -1 ); VICIntEnClear = (1<<inum); // Disable Interrupt VICIntSelect &= (~(1<<inum)); // Classifies as IRQ #if defined LPC2300 *(ulong *)(&VICVectAddr0 + inum) = (ulong)handler; // Set Handler *(ulong *)(&VICVectPriority0 + inum) = priority; #else *(ulong *)(&VICVectAddr0 + priority ) = (ulong)handler; *(ulong *)(&VICVectCntl0 + priority ) = ( 0x20 | inum ); // Enable vector interrupt #endif if( irq_enable ) VICIntEnable = (1<<inum); // Enable Interrupt return( 0 ); } Заодно годится для PL190 и PL192 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться