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

 
 
> UART0 LPC2468, Работа по прерыванию
mempfis_
сообщение Jun 3 2009, 21:36
Сообщение #1


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

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Всем доброй ночи.
Пытаюсь наладить работу с UART0 по прерыванию.

За основу взял рабочий пример из IARa и слегка переделал его по-своему (в основном только инициализация UART0).

Основной цикл программы:
CODE
#include "common/target.h"
#include "common/target.c"

#include "uart_lpc2468.h"
#include "uart_lpc2468.c"

void main(void)
{
//power on target init
TargetResetInit();

//uart0 initialization
uart0_lpc2468_init(9600);


for(;;)
{
//putchar(getchar());
//continue;
/* Loop forever */
if ( UART0Count != 0 )
{
U0IER = IER_THRE | IER_RLS; /* Disable RBR */
UARTSend( (BYTE *)UART0Buffer, UART0Count );
UART0Count = 0;
U0IER = IER_THRE | IER_RLS | IER_RBR; /* Re-enable RBR */
};
}
}


Нстройка UART0:
CODE
/**************************************************/
//uart0 initialization
WORD uart0_lpc2468_init(DWORD baudrate)
{
DWORD Fdiv;

//set PCUART0 - UART0 power/clock control bit.
PCONP |=(1<<PCUART0);

//set PCLK_UART0=0x01 (PCLK_UART0 = CCLK) - Peripheral clock selection for UART0.
PCLKSEL0 |= PCLK_UART0;

//UART pins and pin modes
PINSEL0 = RXPinON|TXPinON;
PINMODE0 = RXPinPullUP|TXPinPullUP;

//UART0 Line Control Register U0LCR
U0LCR = WordLenth8|StopBit1|ParityDis|BreakDis|DLABEna;

//UART0 baudrate
Fdiv = ( Fpclk / 16 ) / baudrate ; /*baud rate */
U0DLM = Fdiv / 256;
U0DLL = Fdiv % 256;
U0LCR = WordLenth8|StopBit1|ParityDis|BreakDis|DLABDis;

//UARTn FIFO Control Register U0FCR
U0FCR = FIFOEna|RXFIFORes|TXFIFORes|TriggerLevel0;

//install uart0 irq
if ( install_irq( UART0_INT, (void *)UART0Handler, HIGHEST_PRIORITY ) == FALSE )
{
return (FALSE);
}

U0IER = RBR_IE | THRE_IE | IER_RLS; /* Enable UART0 interrupt */

return TRUE;
}
/**************************************************/


Инсталяция прерывания:
CODE
DWORD install_irq( DWORD IntNumber, void *HandlerAddr, DWORD Priority )
{
DWORD *vect_addr;
DWORD *vect_cntl;

VICINTENCLEAR = 1 << IntNumber; /* Disable Interrupt */
if ( IntNumber >= VIC_SIZE )
{
return ( FALSE );
}
else
{
/* find first un-assigned VIC address for the handler */
vect_addr = (DWORD *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + IntNumber*4);
vect_cntl = (DWORD *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + IntNumber*4);
*vect_addr = (DWORD)HandlerAddr; /* set interrupt vector */
*vect_cntl = Priority;
VICINTENABLE = 1 << IntNumber; /* Enable Interrupt */
return( TRUE );
}
}


И сам обработчик:
CODE
__irq __arm void UART0Handler(void)
{
BYTE IIRValue, LSRValue;
volatile BYTE Dummy;

//__enable_interrupt(); /* handles nested interrupt */

IIRValue = U0IIR;
IIRValue >>= 1; /* skip pending bit in IIR */
IIRValue &= 0x07; /* check bit 1~3, interrupt identification */
if ( IIRValue == IIR_RLS ) /* Receive Line Status */
{
LSRValue = U0LSR;
/* Receive Line Status */
if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) )
{
/* There are errors or break interrupt */
/* Read LSR will clear the interrupt */
UART0Status = LSRValue;
Dummy = U0RBR; /* Dummy read on RX to clear interrupt, then bail out */
VICADDRESS = 0; /* Acknowledge Interrupt */
return;
}
if ( LSRValue & LSR_RDR ) /* Receive Data Ready */
{
/* If no error on RLS, normal ready, save into the data buffer. */
/* Note: read RBR will clear the interrupt */
//Dummy = U0RBR;
UART0Buffer[UART0Count] = U0RBR;
UART0Count++;
if ( UART0Count == BUFSIZE )
{
UART0Count = 0; /* buffer overflow */
}
}
}
else if ( IIRValue == IIR_RDA ) /* Receive Data Available */
{
/* Receive Data Available */
UART0Buffer[UART0Count] = U0RBR;
UART0Count++;
if ( UART0Count == BUFSIZE )
{
UART0Count = 0; /* buffer overflow */
}
}
else if ( IIRValue == IIR_CTI ) /* Character timeout indicator */
{
/* Character Time-out indicator */
UART0Status |= 0x100; /* Bit 9 as the CTI error */
}
else if ( IIRValue == IIR_THRE ) /* THRE, transmit holding register empty */
{
/* THRE interrupt */
LSRValue = U0LSR; /* Check status in the LSR to see if valid data in U0THR or not */
if ( LSRValue & LSR_THRE )
{
UART0TxEmpty = 1;
}
else
{
UART0TxEmpty = 0;
}
}

VICADDRESS = 0; /* Acknowledge Interrupt */
return;
}
/**************************************************/


Если собрать всё до кучи то по прерываниям не работает sad.gif
Кажется прерывания не возникают вообще. Если вместо прерывания использовать ф-ции getchar/putchar которые просто ожидают/отправляют символы то видно что сам UART0 работает (проверяю работу в терминале).
Т.к. это первое прерывание которое я пытаюсь использовать то сразу уловить не могу в чём тут загвоздка.
Подскажите где что я не так сделал.

Дополнительно прикладываю свой проект и рабочий пример из IARa.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
zltigo
сообщение Jun 4 2009, 07:23
Сообщение #2


Гуру
******

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



Совет - напишите просто что нибудь свое, пусть это бужет для начала 10 строчек, но это будут Ваши 10 строчек и Вы будете понимать, как оно все работает. Только потом уже переходите к использованию 10 чужих подпрограмм и бога ради относитесь ко всяким исходникаи их интернету скептически. Я все, что Вы выложили просто не читал, но так взглядом зацепился за шедевр безвестного "мастера" install_irq(). Ну хотя-бы так.
Код
DWORD install_irq( DWORD IntNumber, void *HandlerAddr, DWORD Priority )
{
/*
Ненужности
DWORD *vect_addr;
DWORD *vect_cntl;
*/

/* Сначала запретили, потом думать начали :(
VICINTENCLEAR = 1 << IntNumber; // Disable Interrupt
*/
  if ( IntNumber >= VIC_SIZE )
  {
    return ( FALSE );
  }
  else
  {
    VICINTENCLEAR = 1 << IntNumber; /* Disable Interrupt */
// А об этом забыли :(, мелочь, но при перепрограмировании может вылезти боком
    VICINTSELECT &= (~(1<<IntNumber));     // Classifies as IRQ

// Мрачновато :(
// DWORD *vect_addr;
// DWORD *vect_cntl;
//    /* find first un-assigned VIC address for the handler */
//    vect_addr = (DWORD *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + IntNumber*4);
//    vect_cntl = (DWORD *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + IntNumber*4);
//    *vect_addr = (DWORD)HandlerAddr;  /* set interrupt vector */
//    *vect_cntl = Priority;

// На Cи это пишется так

    *(DWORD *)(&VICVECTADDR0     + inum) = (DWORD)HandlerAddr;
    *(DWORD *)(&VICVECTPRIORITY0 + inum) = Priority;


    VICINTENABLE = 1 << IntNumber;  /* Enable Interrupt */
    return( TRUE );
  }
}


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Jun 4 2009, 19:49
Сообщение #3


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

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Переписал интсалляцию IRQ (после прочтения документации на VIC-контроллер интуитивно определил регистры которые нужно инициализировать).
К сожалению эхо не возвращается (c putchar/getchar эхо рботает).

Код
DWORD install_irq( DWORD IntNumber, void *HandlerAddr, DWORD Priority )
{
  //очищаем все программные прерывания (ну на всякий случай)
  VICSOFTINTCLEAR = 0xffffffff;
  
  //перед изменением запрещаем соотв. прерывание
  VICINTENCLEAR = (1<<IntNumber);
  
  //определяем соотв. прерывание как IRQ
  VICINTSELECT &= ~(1<<IntNumber);
  
  //устанавливаем приоритет прерывания
  *(DWORD *)(&VICVECTPRIORITY0 + IntNumber) = Priority&0xF;
  
  //сохраняем адрес прерывания
  *(DWORD *) (&VICVECTADDR0 + IntNumber) = (DWORD) HandlerAddr;

  //разрешаем соотв прерывание
    VICINTENABLE = (1 << IntNumber);  /* Enable Interrupt */
    return( TRUE );
}


P.S. чтож тут так всё сложно и запутанно sad.gif
ATmeg-у освоил за неделю. А с ARM столько проблем...
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jun 4 2009, 20:27
Сообщение #4


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(mempfis_ @ Jun 4 2009, 23:49) *
P.S. чтож тут так всё сложно и запутанно sad.gif
ATmeg-у освоил за неделю. А с ARM столько проблем...

Боюсь спросить... rolleyes.gif но все же спрошу, а прерывания в самом АРМ ядре вы не забыли включить ?
Настройка VIC это конечно хорошо, но если прерывания запрещены то можно было и не настраивать smile.gif
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Jun 5 2009, 05:47
Сообщение #5


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

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Про UART0 я прочитал в самую первую очередь. Он у меня даже работает (без прерываний) smile.gif
To zltigo спасибо за код и по VIC и по UART.

To zltigo and singlskv по поводу глобального разрешения прерываний - встроенноя в иар функция __enable_interrupt() позволяет это сделать? Или это необходимо делать вручную например так CPSR |=(1<<I) ?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 5 2009, 07:23
Сообщение #6


Гуру
******

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



Цитата(mempfis_ @ Jun 5 2009, 08:47) *
Он у меня даже работает (без прерываний) smile.gif

Это давно понятно, а прерывания генерить UART разрешено-то?
Код
    // Setup the divisor.
    U0LCR |= LCR_DLAB;
    U0DLL = (uchar)( divisor );
    U0DLM = (uchar)( divisor >> 8 );
    // Turn on the FIFO's and clear the buffers.
    U0FCR = FCR_FCRE|FCR_CLEAR_FIFO;
    // Setup transmission format.
    U0LCR = LCR_NO_PARITY|LCR_1STOP_BIT|LCR_8BIT_CHARS;
    install_irq( VIC_UART0, (void *)uart_isr, VIC_UART0_PRIOR );
    // Enable UART0 interrupts
    U0IER = IER_RDAIE|IER_THREIE;

Цитата
__enable_interrupt() позволяет это сделать?

Разумеется да,тем более, что руками могут и не дать.


--------------------
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 Текстовая версия Сейчас: 22nd July 2025 - 15:37
Рейтинг@Mail.ru


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