|
|
  |
VIC в LPC23xx, Вопрос по пониманию работы VIC |
|
|
|
Sep 23 2009, 20:33
|
Местный
  
Группа: Свой
Сообщений: 266
Регистрация: 8-12-05
Пользователь №: 11 964

|
Добрый день! У меня в процессе освоения 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 с номером регистра адреса. Сейчас у меня большая часть нужной периферии включилась в проект и успешно в нем трудится, но оставлять такой скользкий момент за плечами не хотелось бы. Пожалуйста, ткните меня в фразу из даташита, где это однозначно определяется! Спасибо!
|
|
|
|
|
Sep 23 2009, 21:08
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Polaris @ Sep 24 2009, 00:33)  С VICIntEnable все понятно, это подробно и четко прописано в даташите на контроллер, тут неоднозначностей нет. А вот с адресом не совсем понятно. В данном примере, случайно или нет, бит, взведенный в VICIntEnable, совпадает с номером регистра адреса. Но из текста (особенно в даташите скудно об этом написано), следует вроде бы, что никакой связи нет, регистры равноправны и опрашиваются последовательно. Или я неправильно понял? Не понимаю, если честно, Ваших затруднений - как иначе контроллеру знать, какой VICVectAddr использовать? Возможно, путаница происходит из-за того, что раньше NXP использовали контроллер PL190, у которого каждый источник можно было привязать к любой паре Addr/Cntl, в то время как на новых кристаллах ставят PL192. А примеры просто забыли поправить. Полную документацию на них можно найти здесь.
|
|
|
|
|
Sep 23 2009, 22:08
|
Местный
  
Группа: Свой
Сообщений: 266
Регистрация: 8-12-05
Пользователь №: 11 964

|
Цитата(aaarrr @ Sep 24 2009, 00:08)  Не понимаю, если честно, Ваших затруднений - как иначе контроллеру знать, какой VICVectAddr использовать? Возможно, путаница происходит из-за того, что раньше NXP использовали контроллер PL190, у которого каждый источник можно было привязать к любой паре Addr/Cntl, в то время как на новых кристаллах ставят PL192. А примеры просто забыли поправить. Полную документацию на них можно найти здесь. Вот я тоже так подумал, откуда ему знать, поэтому и поправил сам везде. А примеры, наверное, действительно забыли исправить, что не есть хорошо в книге для начинающих. Если все так обстоит, то вопрос можно закрывать - разобрался  Спасибо за ответ!!!
|
|
|
|
|
Sep 24 2009, 09:32
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Цитата(Polaris @ Sep 24 2009, 02:08)  Если все так обстоит Можете точно убедиться - прочитать user manual на какой-нибудь процессор из старой серии (например, LPC2138) и сравнить раздел VIC  Инициализация в таком случае будет выглядеть так (LPC2138, EINT2): Код VICIntSelect &= ~BIT(16); VICVectAddr1 = (void*)BusyHandler; VICVectCntl1 = 0x20 | 16; VICIntEnable = BIT(16); Похоже?
Сообщение отредактировал esaulenka - Sep 24 2009, 09:34
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Sep 24 2009, 10:19
|
Местный
  
Группа: Свой
Сообщений: 266
Регистрация: 8-12-05
Пользователь №: 11 964

|
Цитата(esaulenka @ Sep 24 2009, 12:32)  Можете точно убедиться - прочитать user manual на какой-нибудь процессор из старой серии (например, LPC2138) и сравнить раздел VIC  Инициализация в таком случае будет выглядеть так (LPC2138, EINT2): Код VICIntSelect &= ~BIT(16); VICVectAddr1 = (void*)BusyHandler; VICVectCntl1 = 0x20 | 16; VICIntEnable = BIT(16); Похоже?  Очень похоже!!! Значит, Мартин проглядел этот момент, адаптируя книгу под LPC23xx/24xx. Спасибо за разъяснения! Цитата(rezident @ Sep 24 2009, 00:27)  Вообще-то в нормальной технической литературе описание общих принципов работы ядра и периферии семейства МК размещают в 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 ); ... Видимо, комментарий по поводу нахождения первого неназначенного адреса из той же оперы. Я лично никакой логической связи между ним и последующим текстом не увидел, а вот сомнения посеялись
|
|
|
|
|
Sep 24 2009, 11:33
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Polaris @ Sep 24 2009, 12:19)  Там в файле 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);
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Sep 25 2009, 07:07
|

Знающий
   
Группа: Свой
Сообщений: 877
Регистрация: 26-01-05
Из: Екатеринбург
Пользователь №: 2 206

|
Цитата(zltigo @ Sep 24 2009, 15:33)  Да тут и исходники уму не растяжимы  , по-человечески это так примерно выглядит: Мой вариант работы с VIC
vic.zip ( 2.58 килобайт )
Кол-во скачиваний: 126Использование выглядит примерно так: Код VIC::set_irq(VIC::TIMER2, sIsrT2); VIC::enable_irq(VIC::TIMER2);
--------------------
Пасу котов...
|
|
|
|
|
Sep 25 2009, 08:25
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Andy Mozzhevilov @ Sep 25 2009, 09:07)  Мой вариант... Использование модифицированных относительно мануала имен портов точно не есть хорошо... Остальное, остальное, типа многочисленных оберток на элементарные действия, "на любителя". Лично я не любитель такой навороченности на ровном месте. Хватает: Код 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
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|