Тестовые утилиты для ЗОСРВ "Нейтрино" редакции 2020
Этот коммит содержится в:
Коммит
558b729c13
|
@ -0,0 +1,2 @@
|
|||
LIST=ALL
|
||||
include recurse.mk
|
|
@ -0,0 +1,42 @@
|
|||
## Дерево исходных кодов
|
||||
|
||||
```
|
||||
|- utils/
|
||||
| |- btime/ - Вывести время с момента включения питания
|
||||
| |- i2c-scan/ - Сканер шины I2C и чтение/запись произвольного регистра I2C устройства
|
||||
| |- int-attach/ - Навесить обработчик прерывания и выводить отладочное сообщение при его возникновении
|
||||
| |- pci-attach/ - Подключиться к PCI устройству
|
||||
| |- rr/ - Чтение/запись произвольного адреса
|
||||
| |- sertest/ - Тест последовательных портов (COM-портов) с передачей, получением и проверкой пакетов с данными
|
||||
| |- spitest/ - Получение/установка конфигурации SPI и тестовый обмен с устройствами на шине
|
||||
| |- ticksize/ - Установка периода срабатывания системного таймера и тест задержки прерывания системного таймера
|
||||
| `- Makefile - Правила сборки дерева исходников
|
||||
|
|
||||
`- Makefile - Правила сборки дерева исходников
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Сборка утилит
|
||||
|
||||
- Установить и настроить [комплект разработчика](https://help.kpda.ru/help/topic/ru.kpda.doc.dev_tools_ru/html/devkit/devkit.html) для [ЗОСРВ "Нейтрино" редакции 2020](https://help.kpda.ru/help/index.jsp).
|
||||
- Выполнить команду:
|
||||
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Запуск утилит
|
||||
|
||||
Примеры представлены в описаниях утилит в каталогах с их исходным кодом:
|
||||
- `btime` - [ссылка на описание утилиты](utils/btime/)
|
||||
- `i2c-scan` - [ссылка на описание утилиты](utils/i2c-scan/)
|
||||
- `int-attach` - [ссылка на описание утилиты](utils/int-attach/)
|
||||
- `pci-attach` - [ссылка на описание утилиты](utils/pci-attach/)
|
||||
- `rr` - [ссылка на описание утилиты](utils/rr/)
|
||||
- `sertest` - [ссылка на описание утилиты](utils/sertest/)
|
||||
- `spitest` - [ссылка на описание утилиты](utils/spitest/)
|
||||
- `ticksize` - [ссылка на описание утилиты](utils/ticksize/)
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
LIST=utils
|
||||
include recurse.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=OS
|
||||
include recurse.mk
|
|
@ -0,0 +1,26 @@
|
|||
### btime
|
||||
|
||||
Вывести время с момента включения питания.
|
||||
|
||||
### Синтаксис
|
||||
```btime [-s "строка"]```
|
||||
|
||||
### Опции
|
||||
- **-s строка**
|
||||
|
||||
опциональная текстовая строка с комментарием
|
||||
|
||||
### Описание
|
||||
|
||||
Утилита выводит время, прошедшее с момента включения питания системы. Значение времени рассчитывается на основе счётчика тактов процессора (см. ClockCycles()).
|
||||
|
||||
Может использоваться для замера времени загрузки системы, например, в загрузочном образе ОС.
|
||||
Можно вызвать несколько раз для вывода значения времени на разных этапах загрузки: запуск ядра ОС, запуск драйверов, прикладного ПО и т.п.
|
||||
|
||||
### Предостережения
|
||||
|
||||
Учтите, что учитывается всё время прошедшее с момента включения питания процессора, включая начальную инициализацию системы, работу загрузчиков, BIOS и т.п.
|
||||
|
||||
### Примеры
|
||||
|
||||
```btime -s "Kernel Boot Time: ```
|
|
@ -0,0 +1,10 @@
|
|||
%C Time passed from board start
|
||||
|
||||
Syntax:
|
||||
%C [options]
|
||||
|
||||
Options:
|
||||
-s descr Description string
|
||||
|
||||
Example:
|
||||
btime -s "Kernel Boot Time: "
|
|
@ -0,0 +1,15 @@
|
|||
ifndef QCONFIG
|
||||
QCONFIG=qconfig.mk
|
||||
endif
|
||||
include $(QCONFIG)
|
||||
|
||||
INSTALLDIR=sbin
|
||||
|
||||
define PINFO
|
||||
PINFO DESCRIPTION=btime
|
||||
endef
|
||||
|
||||
USEFILE=$(PROJECT_ROOT)/btime.use
|
||||
|
||||
include $(MKFILES_ROOT)/qtargets.mk
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Get current cycles counter value by ClockCycles() kernel call.
|
||||
* Print time passed from board start
|
||||
*
|
||||
* (c) 2019, SWD Embedded Systems Limited, http://www.kpda.ru
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/neutrino.h>
|
||||
#include <sys/syspage.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
char *dstr = NULL;
|
||||
uint64_t btime;
|
||||
uint64_t cycles;
|
||||
uint64_t cps;
|
||||
|
||||
while ( ( c = getopt( argc, argv, "s:" ) ) != -1 )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 's': // be verbose
|
||||
dstr = optarg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cps = SYSPAGE_ENTRY(qtime)->cycles_per_sec / 1000;
|
||||
cycles = ClockCycles();
|
||||
btime = cycles / cps;
|
||||
|
||||
printf( "%s %lldms\n", (dstr) ? dstr : "", btime );
|
||||
|
||||
return ( 0 );
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
LIST=CPU
|
||||
include recurse.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=OS
|
||||
include recurse.mk
|
|
@ -0,0 +1,92 @@
|
|||
### i2c-scan
|
||||
|
||||
Сканер шины I2C и чтение/запись произвольного регистра I2C устройства.
|
||||
|
||||
### Синтаксис
|
||||
```i2c-scan [-d устройство] [-f] [-a адрес] [-r смещение] [-w значение] [-c количество]]```
|
||||
|
||||
### Опции
|
||||
- **-d устройство**
|
||||
|
||||
Устройство I2C. Например: /dev/i2c1. По умолчанию: /dev/i2c0
|
||||
|
||||
- **-f**
|
||||
|
||||
Сканировать шину. Задано по умолчанию.
|
||||
|
||||
- **-a адрес**
|
||||
|
||||
Адрес I2C устройства на шине, например, 0x60.
|
||||
|
||||
- **-r смещение**
|
||||
|
||||
Смещение регистра I2C устройства. По умолчанию: 0.
|
||||
|
||||
- **-w значение**
|
||||
|
||||
Значение для записи в регистр устройства.
|
||||
|
||||
- **-c количество**
|
||||
|
||||
Количество регистров для чтения/записи. По умолчанию: 1.
|
||||
|
||||
### Описание
|
||||
|
||||
Утилита i2c-scan сканирует шину I2C, последовательно перебирая доступные адреса (0-127), и выводит таблицу с присутствующими на шине устройствами.
|
||||
|
||||
При задании адреса устройства на шине (опция -a) считывает указанное количество регистров (опция -c) со смещением, заданным опцией -r.
|
||||
|
||||
Пример работы сканера для шин I2C0 и I2C1:
|
||||
```
|
||||
# i2c-scan
|
||||
Scanning I2C device /dev/i2c0 for I2C devices...
|
||||
0 1 2 3 4 5 6 7 8 9 a b c d e f
|
||||
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 6f
|
||||
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
Scanning done
|
||||
#
|
||||
# i2c-scan -d /dev/i2c1
|
||||
Scanning I2C device /dev/i2c1 for I2C devices...
|
||||
0 1 2 3 4 5 6 7 8 9 a b c d e f
|
||||
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
10: -- -- -- -- -- -- -- -- 18 19 -- -- -- -- -- --
|
||||
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
60: 60 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
Scanning done
|
||||
```
|
||||
|
||||
### Предостережения
|
||||
|
||||
I2C устройства, требующие первичной инициализации/включения и/или специфичных многобайтовых транзакций, могут не отображаться сканером шины или не выполнять запросы чтения/записи регистров.
|
||||
|
||||
|
||||
### Примеры
|
||||
|
||||
Сканировать шину I2C0:
|
||||
|
||||
|
||||
```i2c-scan```
|
||||
|
||||
|
||||
Сканировать шину I2C1:
|
||||
|
||||
|
||||
```i2c-scan -d /dev/i2c1```
|
||||
|
||||
|
||||
Считать регистр со смещением 0x50 устройства с адресом 0x60 на шине I2C0
|
||||
|
||||
|
||||
```i2c-scan -a 0x60 -r 0x50```
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
ifndef QCONFIG
|
||||
QCONFIG=qconfig.mk
|
||||
endif
|
||||
include $(QCONFIG)
|
||||
|
||||
USEFILE=$(PROJECT_ROOT)/$(NAME).use
|
||||
INSTALLDIR=sbin
|
||||
|
||||
define PINFO
|
||||
PINFO DESCRIPTION=I2C scan utility
|
||||
endef
|
||||
|
||||
include $(MKFILES_ROOT)/qtargets.mk
|
|
@ -0,0 +1,22 @@
|
|||
%C - I2C scan utility
|
||||
|
||||
Options:
|
||||
-d Device. Default: /dev/i2c0
|
||||
-f Scan I2C bus for devices
|
||||
-a I2C device address
|
||||
-r Register offset
|
||||
-w Value to write to the device
|
||||
-c Number of registers to read/write
|
||||
|
||||
Examples:
|
||||
Scan I2C 0 bus
|
||||
%C
|
||||
|
||||
Scan I2C 1 bus
|
||||
%C -d /dev/i2c1
|
||||
|
||||
Read register 0x50 from I2C device with address 0x60
|
||||
%C -a 0x60 -r 0x50
|
||||
|
||||
Write value 0x2 to register 0x50 from I2C device 0x60
|
||||
%C -a 0x60 -r 0x50
|
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* I2C scan utility
|
||||
*
|
||||
* (c) 2015, SWD Embedded Systems Limited, http://www.kpda.ru
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <hw/i2c.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define REGISTER_SIZE_BYTES 1
|
||||
|
||||
#define UTILITY_MODE_RW 0
|
||||
#define UTILITY_MODE_FIND 1
|
||||
|
||||
|
||||
/* Devctl type SEND pointers: */
|
||||
uint8_t *devctl_send_message; /* Pointer to devctl message */
|
||||
uint8_t *register_send_dev_num; /* Pointer to register number in devctl message */
|
||||
uint8_t *data_send; /* Pointer to data to send in devctl message */
|
||||
i2c_send_t *send_header; /* Pointer to header */
|
||||
|
||||
/* Devctl type SEND-RECEIVE pointers: */
|
||||
uint8_t *devctl_message; /* Pointer to devctl message */
|
||||
i2c_sendrecv_t *send_receive_header; /* Pointer to header */
|
||||
uint8_t *register_dev_num; /* Pointer to register number in devctl message */
|
||||
uint8_t *data; /* Pointer to data to send in devctl message */
|
||||
|
||||
|
||||
/* Desciption: Initialization global structures */
|
||||
void i2c_init()
|
||||
{
|
||||
devctl_message = calloc( 1, sizeof( i2c_sendrecv_t ) + REGISTER_SIZE_BYTES );
|
||||
send_receive_header = (void *)devctl_message;
|
||||
register_dev_num = ((uint8_t *)devctl_message + sizeof( i2c_sendrecv_t ));
|
||||
data = (uint8_t *)register_dev_num;
|
||||
|
||||
devctl_send_message = calloc( 1, sizeof( i2c_send_t ) + REGISTER_SIZE_BYTES + sizeof( uint16_t ) );
|
||||
register_send_dev_num = ((uint8_t *)devctl_send_message + sizeof( i2c_send_t ));
|
||||
data_send = (uint8_t *)((uint8_t *)register_send_dev_num + sizeof( *register_send_dev_num ));
|
||||
send_header = (void *)devctl_send_message;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Desciption: Read value from I2C device
|
||||
* Parameters: device_desc - opened file descriptior
|
||||
* reg_num - register number into device
|
||||
* addr - addr device in I2C bus
|
||||
* Return:
|
||||
* -1 - if error detected
|
||||
* register value - if Ok
|
||||
*/
|
||||
int read_i2c_register( int device_desc, int reg_num, uint8_t addr )
|
||||
{
|
||||
int ret;
|
||||
|
||||
devctl_message = calloc( 1, sizeof( i2c_sendrecv_t ) + REGISTER_SIZE_BYTES );
|
||||
send_receive_header = (void *)devctl_message;
|
||||
register_dev_num = ((uint8_t *)devctl_message + sizeof( i2c_sendrecv_t ));
|
||||
data = (uint8_t *)register_dev_num;
|
||||
*register_dev_num = reg_num;
|
||||
|
||||
send_receive_header->slave.addr = addr;
|
||||
send_receive_header->slave.fmt = I2C_ADDRFMT_7BIT;
|
||||
send_receive_header->send_len = 1;
|
||||
send_receive_header->stop = 1;
|
||||
send_receive_header->recv_len = REGISTER_SIZE_BYTES;
|
||||
ret = devctl( device_desc, DCMD_I2C_SENDRECV, devctl_message, sizeof( i2c_sendrecv_t ) + REGISTER_SIZE_BYTES, NULL );
|
||||
if ( ret )
|
||||
return (-1);
|
||||
else
|
||||
return *data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Desciption: Write value to I2C device
|
||||
* Parameters: device_desc - opened file descriptior
|
||||
* reg_num - register number into device
|
||||
* addr - addr device in I2C bus
|
||||
* value - value to write
|
||||
* Return:
|
||||
* EXIT_FAILURE - error detected,
|
||||
* 0 - if OK
|
||||
*/
|
||||
int write_i2c_register( int device_desc, int reg_num, uint8_t addr, uint16_t value )
|
||||
{
|
||||
int ret;
|
||||
|
||||
*register_send_dev_num = reg_num;
|
||||
*((uint8_t *)data_send) = value;
|
||||
|
||||
send_header->slave.addr = addr;
|
||||
send_header->slave.fmt = I2C_ADDRFMT_7BIT;
|
||||
send_header->len = sizeof( *register_send_dev_num ) + sizeof( *data_send );
|
||||
send_header->stop = 1;
|
||||
|
||||
delay( 10 );
|
||||
ret = devctl( device_desc, DCMD_I2C_SEND, devctl_send_message, sizeof( i2c_send_t ) + send_header->len, NULL );
|
||||
delay( 10 );
|
||||
if ( ret )
|
||||
{
|
||||
fprintf( stderr, "Error writing to register %d device %d value 0x%X.(%s)\n", reg_num, addr, value, strerror( ret ) );
|
||||
return (EXIT_FAILURE);
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
void scan_i2c( int fd )
|
||||
{
|
||||
int i, j;
|
||||
|
||||
fprintf( stderr, " 0 1 2 3 4 5 6 7 8 9 a b c d e f\n" );
|
||||
|
||||
for ( j = 0; j < 128; j += 16 )
|
||||
{
|
||||
fprintf( stderr, "%02x: ", j );
|
||||
for ( i = 0; i < 16 ; i++ )
|
||||
{
|
||||
if ( read_i2c_register( fd, 0, i + j ) >= 0 )
|
||||
fprintf( stderr, "%02x ", i + j );
|
||||
else
|
||||
fprintf( stderr, "-- " );
|
||||
}
|
||||
fprintf( stderr, "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
char *device_name = "/dev/i2c0";
|
||||
int option,
|
||||
device_desc = -1,
|
||||
i,
|
||||
write_value = -1,
|
||||
utility_mode = UTILITY_MODE_FIND,
|
||||
reg_num = 0,
|
||||
addr = 0,
|
||||
val,
|
||||
register_count = 1;
|
||||
|
||||
while ( (option = getopt( argc, argv, "d:a:r:c:w:f" )) != -1 )
|
||||
{
|
||||
switch ( option )
|
||||
{
|
||||
case 'd':
|
||||
device_name = optarg;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
addr = strtol( optarg, NULL, 0 );
|
||||
utility_mode = UTILITY_MODE_RW;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
reg_num = strtol( optarg, NULL, 0 );
|
||||
utility_mode = UTILITY_MODE_RW;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
register_count = strtol( optarg, NULL, 0 );
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
write_value = strtol( optarg, NULL, 0 );
|
||||
utility_mode = UTILITY_MODE_RW;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
utility_mode = UTILITY_MODE_FIND;
|
||||
break;
|
||||
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
device_desc = open( device_name, O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO );
|
||||
if ( device_desc < 0 )
|
||||
{
|
||||
perror( "Failed to open I2C device " );
|
||||
return (-1);
|
||||
}
|
||||
|
||||
i2c_init();
|
||||
|
||||
if ( utility_mode == UTILITY_MODE_FIND )
|
||||
{
|
||||
printf( "Scanning I2C device %s for I2C devices...\n", device_name );
|
||||
scan_i2c( device_desc );
|
||||
printf( "Scanning done \n" );
|
||||
close( device_desc );
|
||||
return (0);
|
||||
}
|
||||
|
||||
printf( "I2C device 0x%X \n", addr );
|
||||
for ( i = 0; i < register_count; i++ )
|
||||
{
|
||||
if ( write_value != -1 )
|
||||
{
|
||||
val = write_i2c_register( device_desc, reg_num + i, addr, write_value );
|
||||
if ( !val )
|
||||
printf( "Writing value 0x%X to register 0x%X\n", write_value, (reg_num + i) );
|
||||
else {
|
||||
fprintf( stderr, "Error writing device 0x%X register 0x%X: (%s)\n", addr, (reg_num + i), strerror( val ) );
|
||||
close( device_desc );
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
val = read_i2c_register( device_desc, reg_num + i, addr );
|
||||
if ( val < 0 )
|
||||
{
|
||||
fprintf( stderr, "Error reading from device 0x%X register 0x%X: (%s)\n", addr, (reg_num + i), strerror( val ) );
|
||||
close( device_desc );
|
||||
return (-1);
|
||||
} else
|
||||
printf( "Reg[0x%02X] = 0x%X\n", reg_num + i, val );
|
||||
}
|
||||
|
||||
close( device_desc );
|
||||
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
LIST=CPU
|
||||
include recurse.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=OS
|
||||
include recurse.mk
|
|
@ -0,0 +1,28 @@
|
|||
### int-attach
|
||||
|
||||
Навесить обработчик прерывания и выводить отладочное сообщение при его возникновении
|
||||
|
||||
### Синтаксис
|
||||
```int-attach -i N```
|
||||
|
||||
### Опции
|
||||
- **-i номер_прерывания**
|
||||
|
||||
навесить обработчик на указанный номер
|
||||
|
||||
### Описание
|
||||
|
||||
Утилита int-attach навешивает минимальный обработчик на заданный номер прерывания и выводит отладочное сообщение при возникновении этого прерывания.
|
||||
Подключаемый обработчик прерывания содержит минимальный код, увеличивающий счётчик количества перехваченных прерываний и маскирующий прерывание. Размаскирование прерывания выполняется в основном потоке функции main() после вывода отладочного сообщения в консоль.
|
||||
|
||||
Может использоваться для отладки и проверки того, что указанное прерывание возникает в ожидаемый момент времени, например, при обращении к аппаратуре, отправка сообщения в COM порт, работа с диском и т.п.
|
||||
Одновременно можно запустить несколько копий программы с различными номерами прерываний.
|
||||
|
||||
### Предостережения
|
||||
|
||||
Учтите, что вывод отладочного сообщения достаточно длительная операция и на это время прерывание будет оставаться замаскированным, что значительно увеличит задержку его обработки в основном драйвере/программ и может нарушить их работу.
|
||||
|
||||
### Примеры
|
||||
|
||||
Навесить обработчик на прерывание 10
|
||||
```int-attach -i 10 &```
|
|
@ -0,0 +1,13 @@
|
|||
ifndef QCONFIG
|
||||
QCONFIG=qconfig.mk
|
||||
endif
|
||||
include $(QCONFIG)
|
||||
|
||||
USEFILE=$(PROJECT_ROOT)/$(NAME).use
|
||||
INSTALLDIR=sbin
|
||||
|
||||
define PINFO
|
||||
PINFO DESCRIPTION=Interrupt attach
|
||||
endef
|
||||
|
||||
include $(MKFILES_ROOT)/qtargets.mk
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Interrupt attach
|
||||
*
|
||||
* (c) 2005, SWD Embedded Systems Limited, http://www.kpda.ru
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/neutrino.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
struct sigevent int_event;
|
||||
int id = -1;
|
||||
unsigned long int_n = 1;
|
||||
volatile unsigned long int_conter = 0;
|
||||
|
||||
|
||||
const struct sigevent *handler( void *area, int id )
|
||||
{
|
||||
InterruptMask( int_n, id );
|
||||
|
||||
int_conter++;
|
||||
|
||||
return (&int_event);
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
int opt;
|
||||
|
||||
// Allow IO operations
|
||||
if ( ThreadCtl( _NTO_TCTL_IO, 0 ) != EOK )
|
||||
{
|
||||
printf( "You must be root!" );
|
||||
return (-1);
|
||||
}
|
||||
|
||||
printf( "Interrupt attach program \n" );
|
||||
|
||||
while ( (opt = getopt ( argc, argv, "i:" )) != -1 )
|
||||
{
|
||||
switch ( opt )
|
||||
{
|
||||
case 'i':
|
||||
int_n = strtoul( optarg, NULL, 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( int_n < 0 )
|
||||
return (-1);
|
||||
else
|
||||
printf( "Attaching handler for interrupt %lu ( 0x%lX ) \n\n", int_n, int_n );
|
||||
|
||||
int_event.sigev_notify = SIGEV_INTR;
|
||||
|
||||
// register an interrupt handler
|
||||
id = InterruptAttach( int_n, &handler, NULL, 0, 0 );
|
||||
|
||||
if ( id == -1 )
|
||||
{
|
||||
perror( " Cannot attach interrupt handler " );
|
||||
return (-1);
|
||||
}
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
InterruptWait( 0, NULL );
|
||||
|
||||
printf( "Got interrupt %lu ( 0x%lX ) #%4ld\n", int_n, int_n, int_conter );
|
||||
InterruptUnmask( int_n, id );
|
||||
}
|
||||
|
||||
InterruptDetach( id );
|
||||
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
%C - interrupt attach
|
||||
|
||||
Options:
|
||||
i <num> - Attach interrupt handler for interrupt <num> (InterruptAttach() is used).
|
||||
Interrupt is masked in interrupt handler and then unmasked in main thread.
|
|
@ -0,0 +1,2 @@
|
|||
LIST=CPU
|
||||
include recurse.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,8 @@
|
|||
LIST=OS
|
||||
ifndef QRECURSE
|
||||
QRECURSE=recurse.mk
|
||||
ifdef QCONFIG
|
||||
QRDIR=$(dir $(QCONFIG))
|
||||
endif
|
||||
endif
|
||||
include $(QRDIR)$(QRECURSE)
|
|
@ -0,0 +1,54 @@
|
|||
### pci-attach
|
||||
|
||||
Подключиться к PCI устройству.
|
||||
|
||||
### Синтаксис
|
||||
```pci-attach [-s] [-v Vendor -d ID] [-arD] [-S]]```
|
||||
|
||||
### Опции
|
||||
- **-s**
|
||||
|
||||
Выполнить сканирование шины PCI и вывести список устройств.
|
||||
|
||||
- **-v PCI_Vendor**
|
||||
- **-d PCI_ID**
|
||||
|
||||
Подключиться к PCI устройству с указанными идентификаторами Vendor и ID.
|
||||
|
||||
- **-a**
|
||||
|
||||
Не отключаться от устройства. По умолчанию: отключиться от устройства после вывода назначенных ресурсов.
|
||||
|
||||
- **-r**
|
||||
|
||||
Смапировать, считать и вывести значения из назначенных PCI устройству диапазонов памяти.
|
||||
|
||||
- **-D**
|
||||
|
||||
Считать и вывести значения из конфигурационной области PCI устройства.
|
||||
|
||||
- **-S**
|
||||
|
||||
Вывести значения из логической базы данных ресурсов PCI сервера (см. rsrcdbmgr_*())
|
||||
|
||||
### Описание
|
||||
|
||||
Утилита *pci-attach* подключается к PCI устройству с помощью функции pci_attach() и выводит назначенные PCI устройству ресурсы: диапазоны памяти и IO, прерывание.
|
||||
|
||||
В отличие от утилиты *pci*, сканирующей шину PCI и выводящей информацию из конфигурационного пространства PCI, но не подключающейся к устройству, *pci-attach* подключается к устройству с заданием флагов инициализации PCI_INIT_ALL и при этом PCI сервер назначает ресурсы устройству, если это требуется.
|
||||
|
||||
### Предостережения
|
||||
|
||||
Если к PCI устройству уже выполнено подключение из драйвера или какой-либо другой программы, то повторное подключение может привести к нарушению их работы.
|
||||
|
||||
### Примеры
|
||||
|
||||
Подключиться к PCI устройству с идентификаторами 0x8086:0x1533 и вывести назначенные устройству PCI ресурсы:
|
||||
|
||||
|
||||
```pci-attach -v 0x8086 -d 0x1533```
|
||||
|
||||
Сканировать шину PCI:
|
||||
|
||||
|
||||
```pci-attach -s```
|
|
@ -0,0 +1,9 @@
|
|||
ifndef QCONFIG
|
||||
QCONFIG=qconfig.mk
|
||||
endif
|
||||
include $(QCONFIG)
|
||||
|
||||
USEFILE=$(PROJECT_ROOT)/$(NAME).use
|
||||
INSTALLDIR=sbin
|
||||
|
||||
include $(MKFILES_ROOT)/qtargets.mk
|
|
@ -0,0 +1,8 @@
|
|||
LIST=CPU
|
||||
ifndef QRECURSE
|
||||
QRECURSE=recurse.mk
|
||||
ifdef QCONFIG
|
||||
QRDIR=$(dir $(QCONFIG))
|
||||
endif
|
||||
endif
|
||||
include $(QRDIR)$(QRECURSE)
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,8 @@
|
|||
LIST=VARIANT
|
||||
ifndef QRECURSE
|
||||
QRECURSE=recurse.mk
|
||||
ifdef QCONFIG
|
||||
QRDIR=$(dir $(QCONFIG))
|
||||
endif
|
||||
endif
|
||||
include $(QRDIR)$(QRECURSE)
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,8 @@
|
|||
LIST=VARIANT
|
||||
ifndef QRECURSE
|
||||
QRECURSE=recurse.mk
|
||||
ifdef QCONFIG
|
||||
QRDIR=$(dir $(QCONFIG))
|
||||
endif
|
||||
endif
|
||||
include $(QRDIR)$(QRECURSE)
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,8 @@
|
|||
LIST=VARIANT
|
||||
ifndef QRECURSE
|
||||
QRECURSE=recurse.mk
|
||||
ifdef QCONFIG
|
||||
QRDIR=$(dir $(QCONFIG))
|
||||
endif
|
||||
endif
|
||||
include $(QRDIR)$(QRECURSE)
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,315 @@
|
|||
/*
|
||||
* PCI attach
|
||||
*
|
||||
* (c) 2013, SWD Embedded Systems Limited, http://www.kpda.ru
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <hw/pci.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/neutrino.h>
|
||||
#include <sys/rsrcdbmgr.h>
|
||||
#include <sys/rsrcdbmsg.h>
|
||||
|
||||
|
||||
int attach_to_device( unsigned vendor, unsigned device, int read_mem, int read_config, int stay_attached, int scan )
|
||||
{
|
||||
void *hdl;
|
||||
struct pci_dev_info pci_info;
|
||||
unsigned *pci_mem;
|
||||
uintptr_t pci_io;
|
||||
uint32_t pci_config[256];
|
||||
int i,
|
||||
j;
|
||||
|
||||
memset( &pci_info, 0, sizeof( pci_info ) );
|
||||
|
||||
if ( scan )
|
||||
{
|
||||
pci_info.BusNumber = vendor;
|
||||
pci_info.DevFunc = device;
|
||||
hdl = pci_attach_device( NULL, PCI_SEARCH_BUSDEV | PCI_SHARE, 0, &pci_info );
|
||||
} else {
|
||||
pci_info.VendorId = vendor;
|
||||
pci_info.DeviceId = device;
|
||||
hdl = pci_attach_device( NULL, PCI_SEARCH_VENDEV | PCI_SHARE, 0, &pci_info );
|
||||
}
|
||||
|
||||
if ( hdl == NULL )
|
||||
{
|
||||
if ( scan == 0 )
|
||||
perror( "Device not found:" );
|
||||
return (-1);
|
||||
}
|
||||
|
||||
printf( "PCI device: %4x:%4x Bus %4d Devfunc %#4x Class %#8x\n",
|
||||
pci_info.VendorId, pci_info.DeviceId, pci_info.BusNumber, pci_info.DevFunc, pci_info.Class );
|
||||
|
||||
if ( read_config )
|
||||
{
|
||||
pci_read_config32( pci_info.BusNumber, pci_info.DevFunc, 0, 256, &pci_config );
|
||||
|
||||
printf( "Dumping PCI configuration before pci_attach_device:\n" );
|
||||
|
||||
for ( i = 1; i <= (256 / 4); i++ )
|
||||
{
|
||||
printf( "[0x%2X] 0x%08X ", (i - 1) * 4, pci_config[i - 1] );
|
||||
if ( i % 5 == 0 )
|
||||
printf( "\n" );
|
||||
}
|
||||
printf( "\n\n" );
|
||||
}
|
||||
|
||||
if ( scan )
|
||||
return (0);
|
||||
else
|
||||
hdl = pci_attach_device( hdl, PCI_INIT_ALL | PCI_INIT_ROM | PCI_SHARE |
|
||||
PCI_MASTER_ENABLE | PCI_USE_MSI, 0, &pci_info );
|
||||
|
||||
if ( hdl == NULL )
|
||||
{
|
||||
perror( "PCI attach failed:" );
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if ( read_config )
|
||||
{
|
||||
pci_read_config32( pci_info.BusNumber, pci_info.DevFunc, 0, 256, &pci_config );
|
||||
|
||||
printf( "Dumping PCI configuration after pci_attach_device:\n" );
|
||||
for ( i = 1; i <= (256 / 4); i++ )
|
||||
{
|
||||
printf( "[0x%2X] 0x%08X ", (i - 1) * 4, pci_config[i - 1] );
|
||||
if ( i % 5 == 0 )
|
||||
printf( "\n" );
|
||||
}
|
||||
printf( "\n\n" );
|
||||
}
|
||||
|
||||
if ( pci_info.Irq != 0xff )
|
||||
printf ("Interrupt %#x (%d)\n", pci_info.Irq, pci_info.Irq );
|
||||
|
||||
for ( i = 0; i < 6; i++ )
|
||||
{
|
||||
if ( pci_info.BaseAddressSize[i] )
|
||||
{
|
||||
if ( PCI_IS_IO( pci_info.CpuBaseAddress[i] ) )
|
||||
{
|
||||
printf( "[%d] IO space at %#llx for %#x bytes\n", i,
|
||||
PCI_IO_ADDR( pci_info.CpuBaseAddress[i] ), pci_info.BaseAddressSize[i] );
|
||||
|
||||
if ( read_mem )
|
||||
{
|
||||
pci_io = mmap_device_io( 4, PCI_IO_ADDR( pci_info.CpuBaseAddress[i] ) );
|
||||
|
||||
if ( pci_io == MAP_DEVICE_FAILED )
|
||||
{
|
||||
printf( "mmap_device_io for physical address %#llx failed\n",
|
||||
PCI_IO_ADDR( pci_info.CpuBaseAddress[i] ) );
|
||||
continue;
|
||||
}
|
||||
|
||||
munmap_device_io( pci_io, 4 );
|
||||
}
|
||||
} else
|
||||
if ( PCI_IS_MEM( pci_info.CpuBaseAddress[i] ) )
|
||||
{
|
||||
printf( "[%d] Memory space at %#llx for %#x bytes\n", i,
|
||||
PCI_MEM_ADDR( pci_info.CpuBaseAddress[i] ), pci_info.BaseAddressSize[i] );
|
||||
|
||||
if ( read_mem )
|
||||
{
|
||||
pci_mem = mmap_device_memory( NULL, pci_info.BaseAddressSize[i],
|
||||
PROT_READ | PROT_WRITE | PROT_NOCACHE,
|
||||
0, PCI_MEM_ADDR( pci_info.CpuBaseAddress[i] ) );
|
||||
|
||||
if ( pci_mem == MAP_FAILED )
|
||||
{
|
||||
printf( "mmap_device_memory for physical address %#llx failed\n",
|
||||
PCI_MEM_ADDR( pci_info.CpuBaseAddress[i] ) );
|
||||
continue;
|
||||
}
|
||||
|
||||
printf( "Reading from device PCI memory \n" );
|
||||
for ( j = 1; j <= 32; j++ )
|
||||
{
|
||||
printf( "[0x%2X] 0x%08X ", (j - 1) * 4, *(pci_mem + (j - 1)) );
|
||||
if ( j % 5 == 0 )
|
||||
printf( "\n" );
|
||||
}
|
||||
printf( "\n\n" );
|
||||
|
||||
munmap_device_memory( pci_mem, pci_info.BaseAddressSize[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( pci_info.PciRom != 0x0 )
|
||||
{
|
||||
printf( "PCI ROM 0x%llx \n", PCI_ROM_ADDR( pci_info.PciRom ) );
|
||||
|
||||
if ( read_mem )
|
||||
{
|
||||
pci_mem = mmap_device_memory( NULL, pci_info.RomSize,
|
||||
PROT_READ | PROT_WRITE | PROT_NOCACHE,
|
||||
0, PCI_ROM_ADDR( pci_info.PciRom ) );
|
||||
|
||||
if ( pci_mem == MAP_FAILED )
|
||||
{
|
||||
printf( "mmap_device_memory for physical address %#llx failed\n",
|
||||
PCI_ROM_ADDR( pci_info.PciRom ) );
|
||||
pci_detach_device( hdl );
|
||||
return (-1);
|
||||
}
|
||||
|
||||
printf( "Reading from device PCI ROM memory : 0x%X \n", *pci_mem );
|
||||
munmap_device_memory( pci_mem, pci_info.RomSize );
|
||||
}
|
||||
}
|
||||
|
||||
if ( stay_attached == 0 )
|
||||
pci_detach_device( hdl );
|
||||
else
|
||||
while ( 1 )
|
||||
sleep(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void dump_rsrcdbmgr( char *name, int type )
|
||||
{
|
||||
rsrc_alloc_t rsrc[256];
|
||||
int i,
|
||||
cnt;
|
||||
|
||||
cnt = rsrcdbmgr_query( rsrc, sizeof( rsrc ) / sizeof( rsrc[0] ), 0, type );
|
||||
printf( "%s - (%d items):\n", name, cnt );
|
||||
if ( !cnt )
|
||||
return;
|
||||
|
||||
printf( "%-4s %-10s %-10s %s", "Idx", "Start", "End", "Flags\n" );
|
||||
for ( i = 0; i < cnt && i < sizeof( rsrc ) / sizeof( rsrc[0] ); i++ )
|
||||
printf( "%3d: %010llx %010llx 0x%x\n",
|
||||
i, rsrc[i].start, rsrc[i].end, rsrc[i].flags );
|
||||
if ( cnt > sizeof( rsrc ) / sizeof( rsrc[0] ) )
|
||||
printf( "...\n" );
|
||||
}
|
||||
|
||||
|
||||
void dump_rsrcdbmgr_db()
|
||||
{
|
||||
printf( "\nSystem resource manager database\n" );
|
||||
dump_rsrcdbmgr( "Memory", RSRCDBMGR_MEMORY );
|
||||
dump_rsrcdbmgr( "IRQs", RSRCDBMGR_IRQ );
|
||||
dump_rsrcdbmgr( "PCI Mem", RSRCDBMGR_PCI_MEMORY );
|
||||
dump_rsrcdbmgr( "IO Ports", RSRCDBMGR_IO_PORT );
|
||||
|
||||
printf( "\n-------------------------------------------------\n\n" );
|
||||
printf( "Used resources\n" );
|
||||
dump_rsrcdbmgr( "Memory", RSRCDBMGR_MEMORY|RSRCDBMGR_FLAG_USED );
|
||||
dump_rsrcdbmgr( "IRQs", RSRCDBMGR_IRQ|RSRCDBMGR_FLAG_USED );
|
||||
dump_rsrcdbmgr( "PCI Mem", RSRCDBMGR_PCI_MEMORY|RSRCDBMGR_FLAG_USED );
|
||||
dump_rsrcdbmgr( "IO Ports", RSRCDBMGR_IO_PORT|RSRCDBMGR_FLAG_USED );
|
||||
printf( "\n" );
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
unsigned vendor = 0,
|
||||
device = 0;
|
||||
int read_mem = 0,
|
||||
read_config = 0,
|
||||
scan_flag = 0,
|
||||
stay_attached = 0,
|
||||
system_res = 0,
|
||||
opt,
|
||||
i,
|
||||
j,
|
||||
pd;
|
||||
|
||||
if ( ThreadCtl( _NTO_TCTL_IO, 0 ) == -1 )
|
||||
{
|
||||
printf( "You must be root!" );
|
||||
return (-1);
|
||||
}
|
||||
|
||||
while ( (opt = getopt( argc, argv, "sv:d:arDS" )) != -1 )
|
||||
{
|
||||
switch ( opt )
|
||||
{
|
||||
case 's':
|
||||
scan_flag = 1;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
vendor = strtoul( optarg, NULL, 0 );
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
device = strtoul( optarg, NULL, 0 );
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
stay_attached = 1;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
read_mem = 1;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
read_config = 1;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
system_res = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf( "Unsupported option.\n" );
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
if ( system_res )
|
||||
{
|
||||
dump_rsrcdbmgr_db();
|
||||
return (0);
|
||||
}
|
||||
|
||||
pd = pci_attach( 0 );
|
||||
if ( pd == (-1) )
|
||||
{
|
||||
perror( "pci_attach" );
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if ( scan_flag )
|
||||
{
|
||||
printf( "Scanning PCI bus\n" );
|
||||
for ( i = 0; i < 256; i++ )
|
||||
for ( j = 0; j < 256; j++ )
|
||||
{
|
||||
attach_to_device( i, j, read_mem, read_config, 0, scan_flag );
|
||||
}
|
||||
} else {
|
||||
if ( vendor == 0 || device == 0 )
|
||||
printf( "Provide correct PCI vendor and device ID.\n" );
|
||||
else {
|
||||
printf( "Attaching to PCI device 0x%04X:0x%04X \n", vendor, device );
|
||||
attach_to_device( vendor, device, read_mem, read_config, stay_attached, scan_flag );
|
||||
}
|
||||
}
|
||||
|
||||
pci_detach( pd );
|
||||
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
%C - PCI attach utility
|
||||
|
||||
Options:
|
||||
-s Scan PCI bus
|
||||
-v Vendor ID
|
||||
-d Device ID
|
||||
-a Don't exit and stay attached to PCI device
|
||||
-r Read device PCI BAR memory
|
||||
-D Print device PCI configuration registers
|
||||
-S Print system resource manager database
|
||||
|
||||
Examples:
|
||||
Scan PCI bus
|
||||
%C -s
|
||||
|
||||
Attach to PCI device
|
||||
%C -v 0x8086 -d 0x1533
|
|
@ -0,0 +1,2 @@
|
|||
LIST=OS
|
||||
include recurse.mk
|
|
@ -0,0 +1,45 @@
|
|||
### rr
|
||||
|
||||
Чтение/запись произвольного адреса.
|
||||
|
||||
### Синтаксис
|
||||
```rr адрес количество [значение]```
|
||||
|
||||
### Опции
|
||||
- **адрес**
|
||||
|
||||
Физический адрес памяти в шестнадцатеричном формате. Например: 0x1000000
|
||||
|
||||
- **количество**
|
||||
|
||||
Количество 32х разрядных значений для чтения.
|
||||
|
||||
- **значение**
|
||||
|
||||
32х разрядное значение для записи в память по указанному адресу.
|
||||
|
||||
### Описание
|
||||
|
||||
Утилита *rr* мапирует и считывает 32х разрядное значение с указанного адреса.
|
||||
Для записи значения по указанному адресу задайте третий опциональный параметр.
|
||||
|
||||
|
||||
### Предостережения
|
||||
|
||||
Для чтения/записи указанного адреса используются функции in32()/out32().
|
||||
|
||||
|
||||
### Примеры
|
||||
|
||||
Считать с физического адреса 0x1000000 одно 32х разрядное значение.
|
||||
|
||||
|
||||
```rr 0x1000000 1```
|
||||
|
||||
|
||||
Записать по физическому адресу 0x1000000 значение 0x12345678.
|
||||
|
||||
|
||||
```rr 0x1000000 1 0x12345678```
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
ifndef QCONFIG
|
||||
QCONFIG=qconfig.mk
|
||||
endif
|
||||
include $(QCONFIG)
|
||||
|
||||
USEFILE=$(PROJECT_ROOT)/$(NAME).use
|
||||
INSTALLDIR=sbin
|
||||
|
||||
define PINFO
|
||||
PINFO DESCRIPTION=Read registers
|
||||
endef
|
||||
|
||||
include $(MKFILES_ROOT)/qtargets.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=CPU
|
||||
include recurse.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,2 @@
|
|||
LIST=VARIANT
|
||||
include recurse.mk
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Read/Write registers
|
||||
*
|
||||
* (c) 2005, SWD Embedded Systems Limited, http://www.kpda.ru
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <hw/inout.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/neutrino.h>
|
||||
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
unsigned long long port;
|
||||
int i,
|
||||
num;
|
||||
unsigned val;
|
||||
uintptr_t base;
|
||||
|
||||
if ( argc < 3 || argc > 4 )
|
||||
{
|
||||
printf( " Provide correct arguments. E.g. : rr 0x1000000 1 \n" );
|
||||
return ( -1 );
|
||||
}
|
||||
|
||||
port = strtoull( argv[1], NULL, 16 );
|
||||
num = strtoul( argv[2], NULL, 16 );
|
||||
|
||||
printf( "\nRead %d dwords from 0x%0llX\n", num, port );
|
||||
|
||||
// Allow IO operations
|
||||
if ( ThreadCtl( _NTO_TCTL_IO, 0 ) == -1 )
|
||||
{
|
||||
printf( "You must be root!" );
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if ( (base = mmap_device_io( num, port )) == MAP_DEVICE_FAILED )
|
||||
{
|
||||
perror( "mmap_device_io()" );
|
||||
return (-1);
|
||||
}
|
||||
|
||||
for ( i = 0; i < num; i++ )
|
||||
{
|
||||
printf( " [0x%X]\t 0x%0X\n", i * 4, in32( base + i * 4 ) );
|
||||
}
|
||||
|
||||
if ( argc == 4 )
|
||||
{
|
||||
val = strtoul( argv[3], NULL, 16 );
|
||||
printf( " Writing value 0x%0X -> 0x%0llX \n", val, port );
|
||||
out32( base, val );
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
%C - Read/Write memory
|
||||
|
||||
%C <address> <num> <value>
|
||||
|
||||
Options:
|
||||
<address> Address in hex format. E.g. 0x1000000
|
||||
<num> Number of elements
|
||||
<value> Write value to memory
|
||||
|
||||
Examples:
|
||||
Read memory at 0x1000000
|
||||
%C 0x1000000 1
|
|
@ -0,0 +1,2 @@
|
|||
LIST=OS
|
||||
include recurse.mk
|
|
@ -0,0 +1,80 @@
|
|||
### sertest
|
||||
|
||||
Тест последовательных портов (COM-портов) с передачей, получением и проверкой пакетов с данными.
|
||||
|
||||
### Синтаксис
|
||||
```sertest -m устройство -rw [-p размер] [-d задержка] [-c счётчик] [-v[vv]]```
|
||||
|
||||
### Опции
|
||||
- **-m устройство**
|
||||
|
||||
Устройство последовательного порта. Например: /dev/ser2. По умолчанию: /dev/ser1
|
||||
|
||||
- **-r**
|
||||
|
||||
Режим чтения.
|
||||
|
||||
- **-w**
|
||||
|
||||
Режим записи.
|
||||
|
||||
- **-p размер**
|
||||
|
||||
Размер посылаемого и принимаемого пакета с данными в байтах. По умолчанию: 128 байт.
|
||||
|
||||
- **-d задержка**
|
||||
|
||||
Только для отправляющей стороны: задержка в миллисекундах между оправками данных. По умолчанию: 100 миллисекунд. Задайте 0 для отключения задержки.
|
||||
|
||||
- **-c счётчик**
|
||||
|
||||
Только для отправляющей стороны: количество пакетов для отправки. По умолчанию не задано, бесконечная отправка.
|
||||
|
||||
- **-v[vv]**
|
||||
|
||||
Включение дополнительного отладочного вывода о количестве и составе передаваемых/получаемых пакетов.
|
||||
|
||||
### Описание
|
||||
|
||||
Утилита *sertest* формирует и затем передаёт или принимает пакет с данными через последовательный интерфейс (RS232/RS422/RS485).
|
||||
|
||||
Предполагается, что два порта будут соединены между собой и будет запущено две копии программы: на приём (опция -r) и на передачу (опция -w).
|
||||
|
||||
При приёме проверяется контрольная сумма полученного пакета и, если она не совпадает с ожидаемой, выводится сообщение об ошибке и увеличивается счётчик ошибок CRC.
|
||||
|
||||
### Предостережения
|
||||
|
||||
Размеры пакета с передающей и принимающей стороны должны совпадать.
|
||||
|
||||
При слишком большой интенсивности обмена (большой размер пакет, низкие задержки между оправками) контроллер может не успевать отправлять/принимать данные, будет происходить переполнение аппаратных FIFO контроллера UART и данные будут теряться. Отследить возникновение аппаратных ошибок UART можно по сообщениям от библиотеки io-char в системном журнале sloginfo, например:
|
||||
*io-char: H/W fifo Overrun error on /dev/ser6*
|
||||
В общем случае при наличии подобных ошибок следует снизить интенсивность обмена.
|
||||
|
||||
|
||||
### Примеры
|
||||
|
||||
Перед запуском теста необходимо соединить два COM-порта между собой, открыть две консоли и запустить две копии sertest.
|
||||
|
||||
В первой консоли в режиме чтения из порта /dev/ser1:
|
||||
|
||||
|
||||
```sertest -m /dev/ser1 -v -r```
|
||||
|
||||
|
||||
Во второй консоли в режиме записи из порт /dev/ser2:
|
||||
|
||||
|
||||
```sertest -m /dev/ser2 -v -w```
|
||||
|
||||
|
||||
Увеличить размер пакета до 2048 байт, паузу между оправками снизить до 1мс.
|
||||
С принимающей стороны:
|
||||
|
||||
|
||||
```sertest -m /dev/ser1 -r -p 2048```
|
||||
|
||||
С передающей стороны:
|
||||
|
||||
|
||||
```sertest -m /dev/ser1 -w -p 2048 -d 1```
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
ifndef QCONFIG
|
||||
QCONFIG=qconfig.mk
|
||||
endif
|
||||
include $(QCONFIG)
|
||||
|
||||
INSTALLDIR=sbin
|
||||
|
||||
define PINFO
|
||||
PINFO DESCRIPTION=Serial port test
|
||||
endef
|
||||
|
||||
include $(MKFILES_ROOT)/qtargets.mk
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Serial port test
|
||||
*
|
||||
* (c) 2013, SWD Embedded Systems Limited, http://www.kpda.ru
|
||||
*/
|
||||
|
||||
|
||||
#include "crc16.h"
|
||||
|
||||
|
||||
/* CRC16 implementation acording to CCITT standards */
|
||||
static const unsigned short crc16tab[256]= {
|
||||
0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
|
||||
0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
|
||||
0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,
|
||||
0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,
|
||||
0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,
|
||||
0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,
|
||||
0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,
|
||||
0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,
|
||||
0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,
|
||||
0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,
|
||||
0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,
|
||||
0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,
|
||||
0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,
|
||||
0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,
|
||||
0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,
|
||||
0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,
|
||||
0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,
|
||||
0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,
|
||||
0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,
|
||||
0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,
|
||||
0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,
|
||||
0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,
|
||||
0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,
|
||||
0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,
|
||||
0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,
|
||||
0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,
|
||||
0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,
|
||||
0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,
|
||||
0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,
|
||||
0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,
|
||||
0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,
|
||||
0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0
|
||||
};
|
||||
|
||||
|
||||
unsigned short crc16_ccitt( const void *buf, int len )
|
||||
{
|
||||
register int counter;
|
||||
register unsigned short crc = 0;
|
||||
|
||||
for ( counter = 0; counter < len; counter++ )
|
||||
crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ *(char *)buf++) & 0x00FF];
|
||||
return crc;
|
||||
}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче