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

 
 
> USART0 & at91sam7s256, После настроек по документации не работает
mempfis_
сообщение Mar 31 2010, 08:53
Сообщение #1


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

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



Пытаюсь настроить USART0 для передачи данных в терминал без использования прерываний.
После чтения документации пришёл к таким настройкам:

Код
#define BOARD_MCK 48000000
#define US0_BAUD 115200
#define BAUDRATE0 (BOARD_MCK / US0_BAUD) / 16;

//настройка usart0
void ConfigureUART(void)
{
  //разрешение тактирования uart0
  AT91C_BASE_PMC->PMC_PCER = (1<<AT91C_ID_US0);
  
  // сброс и запрет приёмника/передатчика
  AT91C_BASE_US0->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS;

  //асинхронный режим, 8 бит, 1 стоповый, без чётности, системный клок 48МГц
  AT91C_BASE_US0->US_MR = AT91C_US_USMODE_HWHSH | AT91C_US_CLKS_CLOCK | AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE
                        | AT91C_US_NBSTOP_1_BIT | AT91C_US_CHMODE_NORMAL;
  
  //настройка предделителя частоты
  AT91C_BASE_US0->US_BRGR = BAUDRATE0;
  
  //очищаем прерывания
  AT91C_BASE_US0->US_CSR;
  
  
  //включаем приём/передачу
  AT91C_BASE_US0->US_CR = AT91C_US_RXEN|AT91C_US_TXEN;
  
}
/******************************************************************/


В PIO настраиваю альтернативные функции - PA5/PA6 RXD/TXD соответственно

Код
/*******************************************/
//линии uart
#define RXD (1<<5) //in
#define TXD (1<<6) //out pu

//настройка альтернативных функций
void PIO_alternat_config(void)
{
  //разрешаем альтернативным функциям управлять выводами
  AT91C_BASE_PIOA->PIO_PDR = RXD|TXD;
  
  //разрешаем подтягивающий резистор на TXD
  AT91C_BASE_PIOA->PIO_PPUER = TXD;
  
  //разрешаем альтернативные функции
  AT91C_BASE_PIOA->PIO_ASR = RXD|TXD;
}
/*******************************************/


Для передачи символа определил функцию:

Код
void _putcharSerial0(unsigned char data)
{
  //ожидаем завершения передачи
  //while(!(AT91C_BASE_US0->US_CSR & AT91C_US_TXRDY));
  AT91C_BASE_US0->US_THR = data;
  for(int i=1000000; i; i--);
}


Сначала попробовал опрашивать флаг готовности к передаче и потом пихать символ в US_THR.
Программа зависла как только я попытался передать первый-же символ
(вероятно на строчке ожидания готовности к передаче).
Заменил ожидание на задержку перед отправкой следующего символа - в терминале 0, программа после попытки отправить символ пошла исполняться дальше.
Т.е. полагаю что USART0 всёже не включился.
Хотя я подал на него тактирование, настроил регистры управления, предделитель, включил приём/передачу, настроил альтернативные функции в PIO!

Вопрос - что я упустил в настройках?
Заранее спасибо за ответы smile.gif

Сообщение отредактировал mempfis_ - Mar 31 2010, 08:55
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
_4afc_
сообщение Mar 31 2010, 10:14
Сообщение #2


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

Группа: Свой
Сообщений: 1 262
Регистрация: 13-10-05
Из: Санкт-Петербург
Пользователь №: 9 565



Цитата(mempfis_ @ Mar 31 2010, 11:53) *
Пытаюсь настроить USART0 для передачи данных в терминал без использования прерываний.

Вопрос - что я упустил в настройках?
Заранее спасибо за ответы smile.gif


Меня смущает AT91C_US_USMODE_HWHSH.
И PIO_alternat_config я вызываю сразу после AT91C_BASE_PMC->PMC_PCER = (1<<AT91C_ID_US0);
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Mar 31 2010, 14:26
Сообщение #3


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

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



Продолжение темы smile.gif

Организовал работу по прерывания - настроил уарт, разрешил прерывания по готовности приёмника и передатчика.

Создал обработчик прерывания в котором при возникновении прерывания после передачи байта
проверяется есть ли в фифо уарта данные (хвост не равен голове) и если есть то извлекается следующий байт
а хвост передвигается вперёд.
При приёме байт просто ложится в приёмную фифо.

Код
/******************************************************************/
#define US0_RXBUFSIZE 512
#define US0_TXBUFSIZE 512


//Глобальные переменные
volatile int Rx0Buf[US0_RXBUFSIZE];// the receiver buffer.
int Rx0Head = 0;//
int Rx0Tail = 0;

volatile int Tx0Buf[US0_RXBUFSIZE];// the transmit buffer.
int Tx0Head = 0;//
int Tx0Tail = 0;

//обработчик прерываний usart0
void USART0_ISR(void)
{  
  int status;
  
  //читаем регистр статуса
  status = AT91C_BASE_US0->US_CSR;
    
  if(status & AT91C_US_TXRDY)
  {
    //передача байта завершена
    if (Tx0Tail != Tx0Head)
      {
         AT91C_BASE_US0->US_THR = Tx0Buf[Tx0Tail++];
         if (Tx0Tail >= US0_TXBUFSIZE) Tx0Tail = 0;
      }
  }
    
  if(status & AT91C_US_RXRDY)
  {
    //приём завершён
    Rx0Buf[Rx0Head++] = AT91C_BASE_US0->US_RHR;
    if (Rx0Head >= US0_RXBUFSIZE) Rx0Head = 0;
  }
  
}
/******************************************************************/


Код прекрасно работал в atmegaх. В АRMе при выполнении этого кода программа зависает.
Т.е. входит в обработчик доходит до момента считывания байта из фифо для передачи его в AT91C_BASE_US0->US_THR.
После этого программа вылетает непонятно куда.

Если вставить простое присваивание любого числа передающему регистру (AT91C_BASE_US0->US_THR = 'A') или закоментировать строчку
Код
if (Tx0Tail != Tx0Head)

то видно что прерывание работает - идёт непрерывная передача данных.

Вопрос - как можно объяснить такое поведение программы?
Это что глюк компилятора или я чтото не учитываю при написании программ под 32хбитные контроллеры ARM?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Mar 31 2010, 17:00
Сообщение #4


Гуру
******

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



Цитата(mempfis_ @ Mar 31 2010, 18:26) *
Это что глюк компилятора или я чтото не учитываю при написании программ под 32хбитные контроллеры ARM?

Если в прерывании по передаче не произойдет записи US_THR, то источник прерывания снят не будет, т.е. получите "зависание".
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Apr 1 2010, 07:13
Сообщение #5


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

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



Цитата(aaarrr @ Mar 31 2010, 20:00) *
Если в прерывании по передаче не произойдет записи US_THR, то источник прерывания снят не будет, т.е. получите "зависание".


Спасибо за подсказку.
Перечитал моменты связанные в приёмом/передачей и соответствующими битами в регистре статуса.
Пришел к такому варианту реализации:
(UART настроен. Приёмник и передатчик включены. Разрешено прерывание AT91C_US_RXRDY)

Код
/**************************************************************/
//ложим байт в передающий регистр или фифо
void _putcharSerial0(unsigned char data)
   {
      if ( !(AT91C_BASE_US0->US_IMR & AT91C_US_TXEMPTY) )
      {
        //прерывания по опустошению передающего регистра запрещены (нет передачи)
        //ложим байт в передающий буффер и разрешаем прерывание
        AT91C_BASE_US0->US_THR = data;
        AT91C_BASE_US0->US_IER = AT91C_US_TXEMPTY;
      }
      else
      {
        //выполняется передача - ложим байт в фифо
        Tx0Buf[Tx0Head++] = data;          
        if (Tx0Head >= US0_RXBUFSIZE) Tx0Head = 0;
      }
   }
/**************************************************************/


void _putstring0( const unsigned char           *pData) { while(*pData != 0x00) _putcharSerial0(*pData++); }
#define PutString0(x) do{static const unsigned char  str[]=x; _putstring0(str);}while(0);


/******************************************************************/
//обработчик прерываний usart0
void USART0_ISR(void)
{  
  int status;
  
  //читаем регистр статуса
  status = AT91C_BASE_US0->US_CSR;
    
  if(status & AT91C_US_TXEMPTY)
  {
    //передача байта завершена
    if (Tx0Tail != Tx0Head)
    {
      //есть ещё байты на передачу
      AT91C_BASE_US0->US_THR = Tx0Buf[Tx0Tail++];
      if (Tx0Tail >= US0_TXBUFSIZE) Tx0Tail = 0;
    }
    else
    {
      //больше нет байт на передачу
      //запрещаем прерывания по опустошению передающего регистра
      AT91C_BASE_US0->US_IDR = AT91C_US_TXEMPTY;
    }
  }
    
  if(status & AT91C_US_RXRDY)
  {
    //приём байта завершён
    //считываем байт в фифо
    Rx0Buf[Rx0Head++] = AT91C_BASE_US0->US_RHR;
    if (Rx0Head >= US0_RXBUFSIZE) Rx0Head = 0;
  }
  
}
/******************************************************************/


Всё работает как задумывалось.
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 06:59
Рейтинг@Mail.ru


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