Перейти к содержанию
    

USART0 & at91sam7s256

Пытаюсь настроить 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!

 

Вопрос - что я упустил в настройках?

Заранее спасибо за ответы :)

Изменено пользователем mempfis_

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Вопрос - что я упустил в настройках?

Заранее спасибо за ответы :)

 

Меня смущает AT91C_US_USMODE_HWHSH.

И PIO_alternat_config я вызываю сразу после AT91C_BASE_PMC->PMC_PCER = (1<<AT91C_ID_US0);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Меня смущает AT91C_US_USMODE_HWHSH.

И PIO_alternat_config я вызываю сразу после AT91C_BASE_PMC->PMC_PCER = (1<<AT91C_ID_US0);

 

Да уж моя внимательность при списывании примеров от атмела на грани фантастики.....

Заменил AT91C_US_USMODE_HWHSH на AT91C_US_USMODE_NORMAL всё заработало сразу.

А PIO_alternat_config вызывается в функции настройки PIO которая идёт перед настройкой уарта.

 

Спасибо за подсказку :)

Буду теперь организовывать работу уарта по прерываниям :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Продолжение темы :)

 

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

 

Создал обработчик прерывания в котором при возникновении прерывания после передачи байта

проверяется есть ли в фифо уарта данные (хвост не равен голове) и если есть то извлекается следующий байт

а хвост передвигается вперёд.

При приёме байт просто ложится в приёмную фифо.

 

/******************************************************************/
#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?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это что глюк компилятора или я чтото не учитываю при написании программ под 32хбитные контроллеры ARM?

Если в прерывании по передаче не произойдет записи US_THR, то источник прерывания снят не будет, т.е. получите "зависание".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если в прерывании по передаче не произойдет записи 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;
  }
  
}
/******************************************************************/

 

Всё работает как задумывалось.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Какие именно примеры атмела использовал ?

 

Приеры из папки examples/atmel.

Сейчас стоит другой iar поэтому точнее сказать не могу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...