Как получить значение регистра UART на Raspberry Pi 3? - PullRequest
0 голосов
/ 10 ноября 2018

Я хочу спросить кое-что о получении значения регистров для miniUART в raspberryPi3. Я хочу сделать последовательный передатчик без каких-либо библиотек.

Сначала я создаю программу с помощью termios и проверил, что она работает. и я хочу проверить, какие регистры изменены, когда выполняются библиотечные функции termios. Но когда я печатаю значения, они всегда равны 0. Я не могу найти, в чем проблема ...

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

#define BUF_SIZE 1024
#define BLOCK_SIZE 1024
#define GPIO_BASE 0x7E210000
#define PERI_BASE 0x7E000000
#define UART_BASE (PERI_BASE + 0x00215000)

static volatile unsigned int *IO, *IER, *LCR, *MCR, 
            *LSR, *MSR, *SCRATCH, *CNTL, *STAT, *BAUD, *UART;


void init_reg(int fd);
void print_reg();

int main(int argc, char** argv){
  int sfd = open("/dev/ttyS0", O_RDWR | O_NOCTTY );
  if (sfd == -1){
      printf( " eno : %d\n", errno);
      printf("%s\n", strerror(errno));
      return -1;
  }

  int fd = open("/dev/mem", O_RDWR | O_SYNC);
  if ( fd == -1){
      printf("Fail to open /dev/mem\n");
      return -1;
  }

  init_reg(fd);

  struct termios options;
  tcgetattr(sfd, &options);
  cfsetspeed(&options, B9600);
  print_reg();  
  cfmakeraw(&options);
  options.c_cflag &= ~CSTOPB;
  options.c_cflag |= CLOCAL;
  options.c_cflag |= CREAD;
  options.c_cc[VTIME] = 1;
  options.c_cc[VMIN] = 100;
  tcsetattr(sfd, TCSANOW, &options);
  print_reg();

  return 0;
}

void init_reg(int fd){
  UART = (unsigned int*)mmap(0, BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, UART_BASE);

  IO = UART + 0x40;
  IER = UART + 0x44;
  LCR = UART + 0x4C;
  MCR = UART + 0x50;
  LSR = UART + 0x54;
  MSR = UART + 0x58;
  SCRATCH = UART + 0x5C;
  CNTL = UART + 0x60;
  STAT = UART + 0x64;
  BAUD = UART + 0x68;
}

void print_reg(){
    print_binary("IO", (*IO));
    print_binary("IER",(*IER));
    print_binary("LCR",(*LCR));
    print_binary("MCR",(*MCR));
    print_binary("LSR",(*LSR));
    print_binary("MSR",(*MSR));
    print_binary("CNTL",(*CNTL));
    print_binary("STAT",(*STAT));
    print_binary("BAUD",(*BAUD));
    print_binary("SCRATCH", (*SCRATCH));*/
    return;
}

1 Ответ

0 голосов
/ 12 ноября 2018

Я не могу найти, в чем проблема ..

Проблема в том, что вы неправильно используете адрес, возвращаемый mmap () , который, кстати, вы не смогли проверить.
Возвращенный указатель присваивается указателю типа целое без знака.

static volatile unsigned int ... *UART;
...
  UART = (unsigned int*)mmap(...);

Затем вы пытаетесь получить доступ к содержимому регистров UART, используя (неправильную) арифметику указателей, например:

  IO = UART + 0x40;

Предположительно, 0x40 (и другие смещения, которые вы используете) - это смещение в байтах.

В выражении C <pointer> + <scaler>, <scaler> берется для представления количества с таким же размером, что и тип указателя (например, sizeof(unsigned int)).
Только когда указатель является байтовым указателем, <scaler> будет представлять количество байтов.

Так как UART объявлен как указатель на 4-байтовое слово, ваш расчет указателя в

IO = UART + 0x40;

действительно эквивалентно

IO = (unsigned int *)((unsigned char *)UART + (sizeof(unsigned int) * 0x40));

, где sizeof(unsigned int) равно 4 (байтам), а примененное смещение в четыре раза больше, чем вы предполагали.

Таким образом, вместо доступа к аппаратным регистрам UART, вы читаете случайные (возможно, несуществующие) области памяти. Такая ошибка кодирования может привести к ошибке шины, когда местоположение фактически недействительно.

Вы можете подтвердить эти операторы (или отладить свой код), используя printf () , чтобы сообщить значения UART, IO и другие переменные-указатели.


Обратите внимание, что большинство настроек termios влияют только на программные состояния, а не на регистры UART, причем заметными исключениями являются скорость передачи данных, кадрирование и CRTSCTS (управление потоком HW)

...