Обзор ядра Linux
Поддержка периферии в Linux
В таблице 2.1 приведены сведения о поддерживаемой периферии в Linux 4.14 для различных микросхем.
Микросхема |
Кодовое имя |
Версия ядра Linux |
UART |
MFBSP-SPI |
MFBSP-GPIO |
MFBSP-LPORT |
Ethernet |
---|---|---|---|---|---|---|---|
1892ВМ15Ф |
МС-30SF6 |
Linux 4.14 |
➕ |
➖ |
➕ |
➖ |
➕ |
1892ВК016 |
MCT-04 |
Linux 4.14 |
➕ |
➖ |
➖ |
✖️ |
✖️ |
1892ВМ206 |
MCT-06 |
Linux 4.14 |
➕ |
➕ |
➕ |
➕ |
➕ |
Исходный код ядра Linux
Исходный код ядра Linux содержит:
|
Поддержка драйверов Linux
MFBSP SPI
MFBSP SPI может работать в режиме Master и в режиме Slave.
Далее описан алгоритм передачи данных из MFBSP-SPI0(host) в MFBSP-SPI1(Slave):
включить поддержку spidev, установив параметр
CONFIG_SPI_SPIDEV
включить
CONFIG_MULTICORE_MFBSP
включить
CONFIG_MULTICORE_MFBSP0_SPI_HOST
иCONFIG_MULTICORE_MFBSP1_SPI_DEVICE
в
CONFIG_CMDLINE
требуется дописать параметрspidev.bufsiz
со значением, равным количеству цепочек DMA, умноженным на размер одной цепочки,т.е.CONFIG_MULTICORE_SPI_DMA_COUNT_OF_CHAINS
умножается наCONFIG_MULTICORE_SPI_DMA_ONE_CHAIN_SIZE
. ПараметрCONFIG_CMDLINE
выглядит следующим образом:console=ttyS0,115200N8 root=/dev/ram spidev.bufsiz=163840
в примере, который запускается из user-space, константу
READ_FILE
требуется заменить на файл, из которого программа будет считывать данные и посылать их в MFBSP-SPI1(Slave):#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/wait.h> #include <unistd.h> #include <string.h> #include <linux/ioctl.h> #define SPI0 "/dev/spidev0.0" #define SPI1 "/dev/mc_spi_slave_1" #define READ_FILE "/etc/init.d/1024K_file" #define WRITE_FILE "/etc/init.d/test_spi.txt" #define GET_ONE_CHAIN_SIZE_SPI_SLAVE _IOR('r', 5, int *) #define GET_COUNT_OF_CHAINS_SPI_SLAVE _IOR('r', 6, int *) int file_len = 0; int read_pos = 0; int write_pos = 0; size_t buffer_len; /* Calculate count of symbols in file */ int num_chars(char* path) { int fd_read_file; char filepath[100]; off_t size; strcpy(filepath, path); fd_read_file = open(filepath, O_RDONLY); if (fd_read_file == -1) { printf("Could not open file %s", filepath); return 0; } off_t pos = lseek(fd_read_file, 0, SEEK_CUR); if (pos != (off_t)-1) { size = lseek(fd_read_file, 0, SEEK_END); lseek(fd_read_file, pos, SEEK_SET); } close(fd_read_file); return size; } int main(void) { int fd, fd_write_spi, fd_read_spi, fd_read_file, fd_write_file; char* buffer; int read_size; int write_size; size_t bytes_read; size_t bytes_write; int one_chain_size = 0; int count_of_chains = 0; file_len = num_chars(READ_FILE); fd = open(SPI1, O_RDONLY); if (fd == -1) { printf("open() error\n"); return -1; } ioctl(fd, GET_ONE_CHAIN_SIZE_SPI_SLAVE, &one_chain_size); ioctl(fd, GET_COUNT_OF_CHAINS_SPI_SLAVE, &count_of_chains); buffer_len = one_chain_size * count_of_chains; buffer = (char*)malloc(buffer_len * sizeof(char)); if (buffer == NULL) { printf("cannot allocate %d of memory\n", buffer_len); return -1; } close(fd); fd_write_spi = open(SPI0, O_WRONLY); if (fd_write_spi == -1) { printf("open() error\n"); return -1; } fd_read_spi = open(SPI1, O_RDONLY); if (fd_read_spi == -1) { printf("open() error\n"); return -1; } fd_read_file = open(READ_FILE, O_RDONLY); if (fd_read_file == -1) { printf("open() error\n"); return -1; } fd_write_file = creat(WRITE_FILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); if (fd_write_file == -1) { printf("open() error\n"); return -1; } do { /* Write to SPI */ if (file_len - write_pos > buffer_len) { write_size = buffer_len; write_pos += buffer_len; } else { write_size = file_len - write_pos; write_pos += write_size; } memset(buffer, 0, write_size); bytes_read = read(fd_read_file, buffer, write_size); bytes_write = write(fd_write_spi, buffer, write_size); /* Read from SPI */ if (file_len - read_pos > buffer_len) { read_size = buffer_len; read_pos += buffer_len; } else { read_size = file_len - read_pos; read_pos += read_size; } memset(buffer, 0, read_size); bytes_read = read(fd_read_spi, buffer, read_size); bytes_write = write(fd_write_file, buffer, read_size); } while (read_pos != file_len); close(fd_write_spi); close(fd_read_spi); close(fd_read_file); close(fd_write_file); return 0; }
для того, чтобы убедиться, что переданный файл равен полученному файлу, можено воспользоваться утилитой
diff
:$ diff /etc/init.d/test_file /etc/init.d/test_spi.txt
MFBSP LPORT
MFBSP LPORT может работать в режиме Master и в режиме Slave.
Далее описан пример передачи данных из MFBSP-LPORT0(host) в MFBSP-LPORT1(Slave).
Требуется:
включить
CONFIG_MULTICORE_MFBSP
включить
CONFIG_MULTICORE_MFBSP0_LPORT_HOST
иCONFIG_MULTICORE_MFBSP1_LPORT_DEVICE
в примере, который запускается из user-space, константу
READ_FILE
заменить на файл, из которого программа будет считывать данные и посылать их в MFBSP-LPORT1(Slave):#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/wait.h> #include <unistd.h> #include <string.h> #include <linux/ioctl.h> #define LPORT0 "/dev/lport_0" #define LPORT1 "/dev/lport_1" #define READ_FILE "/etc/init.d/1024K_file" #define WRITE_FILE "/etc/init.d/test_lport.txt" #define LPORT_GET_ONE_CHAIN_SIZE _IOR('l', 7, int *) #define LPORT_GET_COUNT_OF_CHAINS _IOR('l', 8, int *) int file_len = 0; int read_pos = 0; int write_pos = 0; size_t buffer_len; /* Calculate count of symbols in file */ int num_chars(char* path) { int n, c = 0; FILE* fp; char filepath[100]; strcpy(filepath,path); fp = fopen(filepath, "r"); if (fp == NULL) { printf("Could not open file %s", filepath); return 0; } for (n = getc(fp); n != EOF; n = getc(fp)) c = c + 1; fclose(fp); return c; } int main(void) { int fd, fd_write_lport, fd_read_lport, fd_read_file, fd_write_file; char* buffer; int read_size; int write_size; size_t bytes_read; size_t bytes_write; int one_chain_size = 0; int count_of_chains = 0; file_len = num_chars(READ_FILE); fd = open(LPORT0, O_RDONLY); if (fd == -1) { printf("open() error\n"); return -1; } ioctl(fd, LPORT_GET_ONE_CHAIN_SIZE, &one_chain_size); ioctl(fd, LPORT_GET_COUNT_OF_CHAINS, &count_of_chains); buffer_len = one_chain_size * count_of_chains; buffer = (char*)malloc(buffer_len * sizeof(char)); if (buffer == NULL) { printf("cannot allocate %d of memory\n", buffer_len); return -1; } close(fd); fd_write_lport = open(LPORT0, O_WRONLY); if (fd_write_lport == -1) { printf("open() error\n"); return -1; } fd_read_lport = open(LPORT1, O_RDONLY); if (fd_read_lport == -1) { printf("open() error\n"); return -1; } fd_read_file = open(READ_FILE, O_RDONLY); if (fd_read_file == -1) { printf("open() error\n"); return -1; } fd_write_file = creat(WRITE_FILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); if (fd_write_file == -1) { printf("open() error\n"); return -1; } do { /* Write to LPORT */ if (file_len - write_pos > buffer_len) { write_size = buffer_len; write_pos += buffer_len; } else { write_size = file_len - write_pos; write_pos += write_size; } bytes_read = read(fd_read_file, buffer, write_size); bytes_write = write(fd_write_lport, buffer, write_size); sleep(1); /* Read from LPORT */ if (file_len - read_pos > buffer_len) { read_size = buffer_len; read_pos += buffer_len; } else { read_size = file_len - read_pos; read_pos += read_size; } bytes_read = read(fd_read_lport, buffer, read_size); bytes_write = write(fd_write_file, buffer, read_size); sleep(1); } while (bytes_read != 0); close(fd_write_lport); close(fd_read_lport); close(fd_read_file); close(fd_write_file); return 0; }
MFBSP GPIO
В таблице 2.2 приведены сведения о подключенных к MFBSP GPIO светодиодах для различных плат
Плата |
Интерфейс |
Выводы |
---|---|---|
MC-30SF6EM-6U |
MFBSP3 |
LDAT3_0-7 LACK3 LCLK3 |
MCT-04EM-3U |
MFBSP0 |
LDAT0_5-7 |
MCT-06EM-6U |
MFBSP0 |
LDAT0_4-7 |
✖️ - отсутствие светодиодов, подключенных к MFBSP GPIO
В таблице 2.3 приведено соотвествие внешнего вывода MFBSP GPIO и номера GPIO
Внешний вывод MFBSP GPIO |
GPIO |
---|---|
LACK |
GPIO0 |
LCLK |
GPIO1 |
LDAT[0:7] |
GPIO[2:9] |
Далее описан пример взаимодействия с MFBSP0 LDAT0_4 (GPIO6) на MCT-06EM-6U, который включает LED0.
Требуется:
включить
CONFIG_MULTICORE_MFBSP
включить
CONFIG_MULTICORE_MFBSP0_GPIO
Далее описаны команды взаимодействия c GPIO6 через sysfs:
Включаем GPIO6. 06 - MFBSP0, LDAT0_4:
$ echo "06" > /sys/class/gpio/export
Устанавливаем направление для GPIO. Возможные варианты - out или in:
$ echo "out" > /sys/class/gpio/gpio6/direction
Устанавливаем значение GPIO4. Возможные варианты - 1 или 0:
$ echo "1" > /sys/class/gpio/gpio6/value
Наблюдаем горящий светодиод LED0
Ethernet
Для MCT-06 включение драйвера Ethernet происходит
через CONFIG_MULTICORE_ETH
. Для остальных микросхем включение
драйвера Ethernet происходит через CONFIG_MULTICORE_NEW_ETH_DRV
.
Запуск теста Ethernet:
на host-машине, которая находится в одной сети с target:
$ iperf -s;
на target-системе выполнить (1.2.3.4-ip-адрес host-машины):
$ iperf -c 1.2.3.4