реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> VIC в LPC23xx, Вопрос по пониманию работы VIC
Polaris
сообщение Sep 23 2009, 20:33
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 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 с номером регистра адреса.
Сейчас у меня большая часть нужной периферии включилась в проект и успешно в нем трудится, но оставлять такой скользкий момент за плечами не хотелось бы. Пожалуйста, ткните меня в фразу из даташита, где это однозначно определяется!
Спасибо!
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Sep 23 2009, 21:08
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Polaris @ Sep 24 2009, 00:33) *
С VICIntEnable все понятно, это подробно и четко прописано в даташите на контроллер, тут неоднозначностей нет. А вот с адресом не совсем понятно. В данном примере, случайно или нет, бит, взведенный в VICIntEnable, совпадает с номером регистра адреса. Но из текста (особенно в даташите скудно об этом написано), следует вроде бы, что никакой связи нет, регистры равноправны и опрашиваются последовательно. Или я неправильно понял?

Не понимаю, если честно, Ваших затруднений - как иначе контроллеру знать, какой VICVectAddr использовать?
Возможно, путаница происходит из-за того, что раньше NXP использовали контроллер PL190, у которого каждый источник можно было привязать к любой паре Addr/Cntl, в то время как на новых кристаллах ставят PL192. А примеры просто забыли поправить.
Полную документацию на них можно найти здесь.
Go to the top of the page
 
+Quote Post
rezident
сообщение Sep 23 2009, 21:27
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Вообще-то в нормальной технической литературе описание общих принципов работы ядра и периферии семейства МК размещают в User's Manual. А в datasheet находится уточняющая информация о конкретных характеристиках одного или нескольких кристаллов из семейства. Так что вам нужно видимо UM10211 LPC23XX User manual читать, а не только datasheet.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Sep 23 2009, 21:32
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Да нет, там и в мануале описание VIC урезано до предела, т.к. это стандартное решение от ARM. Правда, могли бы и написать, куда обращаться за расширенной информацией.
Go to the top of the page
 
+Quote Post
Polaris
сообщение Sep 23 2009, 22:08
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 266
Регистрация: 8-12-05
Пользователь №: 11 964



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

Вот я тоже так подумал, откуда ему знать, поэтому и поправил сам везде. А примеры, наверное, действительно забыли исправить, что не есть хорошо в книге для начинающих. Если все так обстоит, то вопрос можно закрывать - разобрался smile.gif Спасибо за ответ!!!
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Sep 24 2009, 09:32
Сообщение #6


Профессионал
*****

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



Цитата(Polaris @ Sep 24 2009, 02:08) *
Если все так обстоит

Можете точно убедиться - прочитать user manual на какой-нибудь процессор из старой серии (например, LPC2138) и сравнить раздел VIC wink.gif

Инициализация в таком случае будет выглядеть так (LPC2138, EINT2):
Код
    VICIntSelect &= ~BIT(16);
    VICVectAddr1 = (void*)BusyHandler;
    VICVectCntl1 = 0x20 | 16;
    VICIntEnable = BIT(16);


Похоже? smile.gif

Сообщение отредактировал esaulenka - Sep 24 2009, 09:34


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
Polaris
сообщение Sep 24 2009, 10:19
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 266
Регистрация: 8-12-05
Пользователь №: 11 964



Цитата(esaulenka @ Sep 24 2009, 12:32) *
Можете точно убедиться - прочитать user manual на какой-нибудь процессор из старой серии (например, LPC2138) и сравнить раздел VIC wink.gif

Инициализация в таком случае будет выглядеть так (LPC2138, EINT2):
Код
    VICIntSelect &= ~BIT(16);
    VICVectAddr1 = (void*)BusyHandler;
    VICVectCntl1 = 0x20 | 16;
    VICIntEnable = BIT(16);


Похоже? smile.gif

Очень похоже!!! Значит, Мартин проглядел этот момент, адаптируя книгу под 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 );
...
Видимо, комментарий по поводу нахождения первого неназначенного адреса из той же оперы. Я лично никакой логической связи между ним и последующим текстом не увидел, а вот сомнения посеялись smile.gif
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Sep 24 2009, 11:15
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Ну дык copy-paste все любят, а вот комментарии переделывать лень.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Sep 24 2009, 11:33
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 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 */

Да тут и исходники уму не растяжимы sad.gif, по-человечески это так примерно выглядит:
Код
    *(ulong *)(&VICVectAddr0 + IntNumber) = (ulong)HandlerAddr;
    *(ulong *)(&VICVectPriority0 + IntNumber) = Priority;
    VICIntEnable = (1<<IntNumber);


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Andy Mozzhevilov
сообщение Sep 25 2009, 07:07
Сообщение #10


Знающий
****

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



Цитата(zltigo @ Sep 24 2009, 15:33) *
Да тут и исходники уму не растяжимы sad.gif, по-человечески это так примерно выглядит:

Мой вариант работы с VIC Прикрепленный файл  vic.zip ( 2.58 килобайт ) Кол-во скачиваний: 126

Использование выглядит примерно так:
Код
    VIC::set_irq(VIC::TIMER2, sIsrT2);
    VIC::enable_irq(VIC::TIMER2);


--------------------
Пасу котов...
Go to the top of the page
 
+Quote Post
zltigo
сообщение Sep 25 2009, 08:25
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 20:46
Рейтинг@Mail.ru


Страница сгенерированна за 0.01458 секунд с 7
ELECTRONIX ©2004-2016