Ник:
Пароль:

Контакты

E-mail: info@starterkit.ru
тел.: +7 922 680-21-73
тел.: +7 922 680-21-74
Телеграм: t.me/starterkit_ru

Способы оплаты

User Info


Добро пожаловать,
Guest

Регистрация или входРегистрация или вход
Потеряли пароль?Потеряли пароль?

Ник:
Пароль:

ПользователейПользователей:1
Поисковых ботовПоисковых ботов:3
ГостейГостей:1

ОбновитьПодробнееВсегоВсего:5
Форум » starterkit.ru » Отладочные платы » SK-iMX53
Драйвер АЦП
voland
Добавлено 08.07.2013 08:29
0
Сообщение: 1
voland
0

Пункты: 1239
Регистрация: 02.04.2011
Здравствуйте!

Являюсь обладателем данной платы. Попробовал написать драйвер для работы с двумя 16 разрядными АЦП через GPIO.
Частота дискретизации до 60 кГц. При регистрации длительностью 60 сек появляються пропуски в 16 или 17 дискрет суммарно до 500 пропусков. Попытки оптимизации приводят к уменьшению количества пропусков но длительность пропусков (16-17 дискрет) остается неизменной.

В чем может быть причина?

Как я понял в данной реализации контроллер GPIO (pcf953x) последовательный - может не хватает скорости?

Есть ли возможность организовать драйвер обеспечивающий скорость работы по параллельной шине с тактовой частотой до 100 кГц.

Буду благодарен за любую помощь!

Код драйвера:

Код
#define MODULE
#define __KERNEL__

#include <linux/stddef.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/sched.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <asm/unistd.h>
#include "mx53.h"
#include "iomux.h"

//Информация о модуле
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Vladimir Bobrovsky");
MODULE_DESCRIPTION("BBS driver for imx53");
MODULE_SUPPORTED_DEVICE("bbs");

//информация о прерывании
#define IRQ_NUMB MXC_INT_GPIO4_HIGH // Combined interupt indication for GPIO-4 signal 16 throughout 31

//Имя устройства
#define SUCCESS 0
#define DEVICE_NAME "bbs"

// Поддерживаемые операции
static int device_open( struct inode *, struct file * );
static int device_release( struct inode *, struct file * );
static ssize_t device_read( struct file *, char *, size_t, loff_t * );
static ssize_t device_write( struct file *, const char *, size_t, loff_t * );
static int region_size = 256;

// Глобальные переменные
static int major_number; //Старший номер устройства
static int is_device_open = 0; //Признак использования устройства

//Порты ввода вывода
static void *gpio1_base;
static void *gpio2_base;
static void *gpio3_base;
static void *gpio4_base;
static void *gpio5_base;
static void *gpio6_base;
static void *gpio7_base;


static char locked;
static int st1;
static int st2;
static int flag;

//** Флаги
signed char f_key_start = 0; //Флаг старта по кнопке

//** Данные АЦП
static unsigned short int data_adc1,data_adc2,data_st; //Данные АЦП для вывода в файл
static int gd; //Вспомогательная переменная для хранения состояния готовности данных

//** Данные буфера FIFO
#define INPUT_BUFFER_SIZE (1*1024*1024)
#define BYTES_IN_FIFO_IRQ_OCCURS 24 // кол-во байт в фифо когда генерится прерывание (макс 32)

struct {
char data [INPUT_BUFFER_SIZE];
int start;
int end;
} inputBuffer;

static char locked;

//Структура для хранения комманды от программы пользователя
struct dev_command
{
unsigned char command; //Команда запуска - 'B' / остановки - 'E' / 'C' - конфигурирование регистрации
int regim; //Выбор режима работы БУРС
int grad; //Управление сигналом градуировки
int cdpp; //Выбор длительности импульса периодической последовательности
int cdmp; //Выбор количества дискрет в минимальном импульсе М - последовательности
int crmp; //Выбор количества разрядов M - последовательности
int csmp; //Выбор коэффициента деления частоты ГТИ для формирования сигнала Sample
unsigned int samples; //Длинна регистрации в дискретах
};
static struct dev_command command;
static unsigned char buf_command[sizeof(struct dev_command)];
static unsigned int samples;


//Структура для хранения состояния устройства
struct dev_state
{
int dev_open;//Открыто ли устройство
ssize_t byte_read;//Сколько байт прочитано из устройства
ssize_t byte_write;//Сколько байт записано в устройство
};
#define MAX_INODE 2
//Массив для хранения информации о состоянии устройств
static struct dev_state state[MAX_INODE+1];

// Прописываем обработчики операций над устройством
static struct file_operations fops =
{
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release
};


//Переменные для отладки
static int e_irq; //число заходов в обработчик прерываний
static int e_locked; //число ситуаций с занятием времени обработчиком прерываний
static int e_free_buf; //число ситуаций с пустым буфером
static int e_buf; //число ситуаций с недостатком элементов в буфере

// --------- Функции контроля ошибок

// Сброс ошибок
static void reset_error()
{
e_irq=0;
e_locked=0;
e_free_buf=0;
e_buf=0;
}

// Печать ошибок
static void print_error()
{
printk("e_irq = %d\n", e_irq);
printk("e_locked = %d\n", e_locked);
printk("e_free_buf = %d\n", e_free_buf);
printk("e_buf = %d\n", e_buf);
}

// --------- Функции GPIO

// Инициализация портов GPIO для работы с устройствами БУРС
static void gpio_initialization()
{
struct resource *res;
//Инициализация портов ввода-вывода
res= request_mem_region(IOMUX_BASE_ADDR, region_size, "iomux");
iomux_base= ioremap_nocache(IOMUX_BASE_ADDR, region_size);

res= request_mem_region(GPIO1_BASE_ADDR, region_size, "gpio1");
gpio1_base= ioremap_nocache(GPIO1_BASE_ADDR, region_size);

res= request_mem_region(GPIO2_BASE_ADDR, region_size, "gpio2");
gpio2_base= ioremap_nocache(GPIO2_BASE_ADDR, region_size);

res= request_mem_region(GPIO3_BASE_ADDR, region_size, "gpio3");
gpio3_base= ioremap_nocache(GPIO3_BASE_ADDR, region_size);

res= request_mem_region(GPIO4_BASE_ADDR, region_size, "gpio4");
gpio4_base= ioremap_nocache(GPIO4_BASE_ADDR, region_size);

res= request_mem_region(GPIO5_BASE_ADDR, region_size, "gpio5");
gpio5_base= ioremap_nocache(GPIO5_BASE_ADDR, region_size);

res= request_mem_region(GPIO6_BASE_ADDR, region_size, "gpio6");
gpio6_base= ioremap_nocache(GPIO6_BASE_ADDR, region_size);

res= request_mem_region(GPIO7_BASE_ADDR, region_size, "gpio7");
gpio7_base= ioremap_nocache(GPIO7_BASE_ADDR, region_size);

//Конфигурирование устройства
res=gpio_request(7,"7");
res=gpio_request(8,"8");
res=gpio_request(9,"9");

res=gpio_request(32,"32");
res=gpio_request(33,"33");
res=gpio_request(35,"35");
res=gpio_request(38,"38");
res=gpio_request(40,"40");
res=gpio_request(55,"55");
res=gpio_request(59,"59");
res=gpio_request(60,"60");

res=gpio_request(75,"75");
res=gpio_request(77,"77");
res=gpio_request(80,"80");
res=gpio_request(81,"81");
res=gpio_request(82,"82");
res=gpio_request(84,"84");
res=gpio_request(85,"85");
res=gpio_request(87,"87");
res=gpio_request(88,"88");
res=gpio_request(89,"89");
res=gpio_request(91,"91");
res=gpio_request(92,"92");
res=gpio_request(93,"93");

res=gpio_request(102,"102");
res=gpio_request(103,"103");
res=gpio_request(112,"112");
res=gpio_request(113,"113");
res=gpio_request(114,"114");
res=gpio_request(115,"115");
res=gpio_request(117,"117");
res=gpio_request(118,"118");
res=gpio_request(119,"119");
res=gpio_request(120,"120");
res=gpio_request(121,"121");
res=gpio_request(122,"122");
res=gpio_request(123,"123");
res=gpio_request(124,"124");
res=gpio_request(125,"125");
res=gpio_request(126,"126");
res=gpio_request(127,"127");

res=gpio_request(133,"133");
res=gpio_request(134,"134");
res=gpio_request(135,"135");
res=gpio_request(136,"136");
res=gpio_request(137,"137");
res=gpio_request(138,"138");
res=gpio_request(139,"139");
res=gpio_request(140,"140");
res=gpio_request(141,"141");
res=gpio_request(142,"142");
res=gpio_request(143,"143");
res=gpio_request(144,"144");
res=gpio_request(145,"145");
res=gpio_request(146,"146");
res=gpio_request(147,"147");
res=gpio_request(154,"154");
res=gpio_request(155,"155");
res=gpio_request(156,"156");
res=gpio_request(158,"158");
res=gpio_request(159,"159");

res=gpio_request(160,"160");
res=gpio_request(161,"161");
res=gpio_request(162,"162");
res=gpio_request(163,"163");
res=gpio_request(164,"164");
res=gpio_request(165,"165");

res=gpio_request(192,"192");
res=gpio_request(193,"193");
res=gpio_request(196,"196");
res=gpio_request(197,"197");
res=gpio_request(198,"198");
res=gpio_request(202,"202");
res=gpio_request(204,"204");

//Инициализация IOMUX
IOMUX_SW_1_7 = IOMUX_SW_1_7 | IOMUX_SW_1_7_VAL;
IOMUX_SW_1_8 = IOMUX_SW_1_8 | IOMUX_SW_1_8_VAL;
IOMUX_SW_1_9 = IOMUX_SW_1_9 | IOMUX_SW_1_9_VAL;

IOMUX_SW_2_0 = IOMUX_SW_2_0 | IOMUX_SW_2_0_VAL;
IOMUX_SW_2_1 = IOMUX_SW_2_1 | IOMUX_SW_2_1_VAL;
IOMUX_SW_2_3 = IOMUX_SW_2_3 | IOMUX_SW_2_3_VAL;
IOMUX_SW_2_6 = IOMUX_SW_2_6 | IOMUX_SW_2_6_VAL;
IOMUX_SW_2_8 = IOMUX_SW_2_8 | IOMUX_SW_2_8_VAL;
IOMUX_SW_2_23 = IOMUX_SW_2_23 | IOMUX_SW_2_23_VAL;
IOMUX_SW_2_27 = IOMUX_SW_2_27 | IOMUX_SW_2_27_VAL;
IOMUX_SW_2_28 = IOMUX_SW_2_28 | IOMUX_SW_2_28_VAL;
IOMUX_SW_3_11 = IOMUX_SW_3_11 | IOMUX_SW_3_11_VAL;
IOMUX_SW_3_13 = IOMUX_SW_3_13 | IOMUX_SW_3_13_VAL;
IOMUX_SW_3_16 = IOMUX_SW_3_16 | IOMUX_SW_3_16_VAL;
IOMUX_SW_3_17 = IOMUX_SW_3_17 | IOMUX_SW_3_17_VAL;
IOMUX_SW_3_18 = IOMUX_SW_3_18 | IOMUX_SW_3_18_VAL;
IOMUX_SW_3_20 = IOMUX_SW_3_20 | IOMUX_SW_3_20_VAL;
IOMUX_SW_3_21 = IOMUX_SW_3_21 | IOMUX_SW_3_21_VAL;
IOMUX_SW_3_23 = IOMUX_SW_3_23 | IOMUX_SW_3_23_VAL;
IOMUX_SW_3_24 = IOMUX_SW_3_24 | IOMUX_SW_3_24_VAL;
IOMUX_SW_3_25 = IOMUX_SW_3_25 | IOMUX_SW_3_25_VAL;
IOMUX_SW_3_27 = IOMUX_SW_3_27 | IOMUX_SW_3_27_VAL;
IOMUX_SW_3_28 = IOMUX_SW_3_28 | IOMUX_SW_3_28_VAL;
IOMUX_SW_3_29 = IOMUX_SW_3_29 | IOMUX_SW_3_29_VAL;

IOMUX_SW_4_6 = IOMUX_SW_4_6 | IOMUX_SW_4_6_VAL;
IOMUX_SW_4_7 = IOMUX_SW_4_7 | IOMUX_SW_4_7_VAL;
IOMUX_SW_4_16 = IOMUX_SW_4_16 | IOMUX_SW_4_16_VAL;
IOMUX_SW_4_17 = IOMUX_SW_4_17 | IOMUX_SW_4_17_VAL;
IOMUX_SW_4_18 = IOMUX_SW_4_18 | IOMUX_SW_4_18_VAL;
IOMUX_SW_4_19 = IOMUX_SW_4_19 | IOMUX_SW_4_19_VAL;
IOMUX_SW_4_21 = IOMUX_SW_4_21 | IOMUX_SW_4_21_VAL;
IOMUX_SW_4_22 = IOMUX_SW_4_22 | IOMUX_SW_4_22_VAL;
IOMUX_SW_4_23 = IOMUX_SW_4_23 | IOMUX_SW_4_23_VAL;
IOMUX_SW_4_24 = IOMUX_SW_4_24 | IOMUX_SW_4_24_VAL;
IOMUX_SW_4_25 = IOMUX_SW_4_25 | IOMUX_SW_4_25_VAL;
IOMUX_SW_4_26 = IOMUX_SW_4_26 | IOMUX_SW_4_26_VAL;
IOMUX_SW_4_27 = IOMUX_SW_4_27 | IOMUX_SW_4_27_VAL;
IOMUX_SW_4_28 = IOMUX_SW_4_28 | IOMUX_SW_4_28_VAL;
IOMUX_SW_4_29 = IOMUX_SW_4_29 | IOMUX_SW_4_29_VAL;
IOMUX_SW_4_30 = IOMUX_SW_4_30 | IOMUX_SW_4_30_VAL;
IOMUX_SW_4_31 = IOMUX_SW_4_31 | IOMUX_SW_4_31_VAL;

IOMUX_SW_5_5 = IOMUX_SW_5_5 | IOMUX_SW_5_5_VAL;
IOMUX_SW_5_6 = IOMUX_SW_5_6 | IOMUX_SW_5_6_VAL;
IOMUX_SW_5_7 = IOMUX_SW_5_7 | IOMUX_SW_5_7_VAL;
IOMUX_SW_5_8 = IOMUX_SW_5_8 | IOMUX_SW_5_8_VAL;
IOMUX_SW_5_9 = IOMUX_SW_5_9 | IOMUX_SW_5_9_VAL;
IOMUX_SW_5_10 = IOMUX_SW_5_10 | IOMUX_SW_5_10_VAL;
IOMUX_SW_5_11 = IOMUX_SW_5_11 | IOMUX_SW_5_11_VAL;
IOMUX_SW_5_12 = IOMUX_SW_5_12 | IOMUX_SW_5_12_VAL;
IOMUX_SW_5_13 = IOMUX_SW_5_13 | IOMUX_SW_5_13_VAL;
IOMUX_SW_5_14 = IOMUX_SW_5_14 | IOMUX_SW_5_14_VAL;
IOMUX_SW_5_15 = IOMUX_SW_5_15 | IOMUX_SW_5_15_VAL;
IOMUX_SW_5_16 = IOMUX_SW_5_16 | IOMUX_SW_5_16_VAL;
IOMUX_SW_5_17 = IOMUX_SW_5_17 | IOMUX_SW_5_17_VAL;
IOMUX_SW_5_18 = IOMUX_SW_5_18 | IOMUX_SW_5_18_VAL;
IOMUX_SW_5_19 = IOMUX_SW_5_19 | IOMUX_SW_5_19_VAL;
IOMUX_SW_5_26 = IOMUX_SW_5_26 | IOMUX_SW_5_26_VAL;
IOMUX_SW_5_27 = IOMUX_SW_5_27 | IOMUX_SW_5_27_VAL;
IOMUX_SW_5_28 = IOMUX_SW_5_28 | IOMUX_SW_5_28_VAL;
IOMUX_SW_5_30 = IOMUX_SW_5_30 | IOMUX_SW_5_30_VAL;
IOMUX_SW_5_31 = IOMUX_SW_5_31 | IOMUX_SW_5_31_VAL;

IOMUX_SW_6_0 = IOMUX_SW_6_0 | IOMUX_SW_6_0_VAL;
IOMUX_SW_6_1 = IOMUX_SW_6_1 | IOMUX_SW_6_1_VAL;
IOMUX_SW_6_2 = IOMUX_SW_6_2 | IOMUX_SW_6_2_VAL;
IOMUX_SW_6_3 = IOMUX_SW_6_3 | IOMUX_SW_6_3_VAL;
IOMUX_SW_6_4 = IOMUX_SW_6_4 | IOMUX_SW_6_4_VAL;
IOMUX_SW_6_5 = IOMUX_SW_6_5 | IOMUX_SW_6_5_VAL;

IOMUX_SW_7_0 = IOMUX_SW_7_0 | IOMUX_SW_7_0_VAL;
IOMUX_SW_7_1 = IOMUX_SW_7_1 | IOMUX_SW_7_1_VAL;
IOMUX_SW_7_4 = IOMUX_SW_7_4 | IOMUX_SW_7_4_VAL;
IOMUX_SW_7_5 = IOMUX_SW_7_5 | IOMUX_SW_7_5_VAL;
IOMUX_SW_7_6 = IOMUX_SW_7_6 | IOMUX_SW_7_6_VAL;
IOMUX_SW_7_10 = IOMUX_SW_7_10 | IOMUX_SW_7_10_VAL;
IOMUX_SW_7_12 = IOMUX_SW_7_12 | IOMUX_SW_7_12_VAL;

//Инициализация портов GPIO
gpio_direction_output(7, 0); //Сигнал AS - мультиплексирование шины данных АЦП
gpio_direction_output(8, 0); //Сигнал IN_CAL - запуск калибровки АЦП
gpio_direction_output(9, 0); //Сигнал E_DOUT1 - управление разрешением выборки АЦП

gpio_direction_input(32); //Сигнал PIN9
gpio_direction_input(33); //Сигнал PIN15
gpio_direction_input(35); //Сигнал PIN10
gpio_direction_input(38); //Сигнал PIN11
gpio_direction_input(40); //Сигнал PIN8
gpio_direction_input(55); //Сигнал PIN3
gpio_direction_output(59, 0); //Сигнал CRMP1 - управление разрядностью М - последовательности ФЦП
gpio_direction_output(60, 0); //Сигнал CRMP2 - управление разрядностью М - последовательности ФЦП

gpio_direction_input(75); //Сигнал PIN2
gpio_direction_output(77, 0); //Сигнал PIN1
gpio_direction_input(80); //Сигнал PIN6
gpio_direction_input(81); //Сигнал PIN7
gpio_direction_input(82); //Сигнал PIN4
gpio_direction_input(84); //Сигнал KEY1 - кнопка 1 экрана
gpio_direction_input(85); //Сигнал KEY2 - кнопка 2 экрана
gpio_direction_input(87); //Сигнал KEY3 - кнопка 3 экрана
gpio_direction_input(88); //Сигнал KEY4 - кнопка 4 экрана
gpio_direction_input(89); //Сигнал KEY5 - кнопка 5 экрана
gpio_direction_input(91); //Сигнал KEY6 - кнопка 6 экрана
gpio_direction_input(92); //Сигнал KEY7 - кнопка 7 экрана
gpio_direction_input(93); //Сигнал KEY8 - кнопка 8 экрана

gpio_direction_output(102, 0); //Сигнал CSMP7 - кофициент деления импульсов ГТИ для формирования сигнала Sample ФЦП
gpio_direction_output(103, 0); //Сигнал CSMP8 - кофициент деления импульсов ГТИ для формирования сигнала Sample ФЦП
gpio_direction_output(112, 0); //Сигнал CSMP9 - кофициент деления импульсов ГТИ для формирования сигнала Sample ФЦП
gpio_direction_output(113, 0); //Сигнал CSMP10 - кофициент деления импульсов ГТИ для формирования сигнала Sample ФЦП
gpio_direction_output(114, 0); //Сигнал CSMP11 - кофициент деления импульсов ГТИ для формирования сигнала Sample ФЦП
gpio_direction_output(115, 0); //Сигнал CSMP12 - кофициент деления импульсов ГТИ для формирования сигнала Sample ФЦП
gpio_direction_input(117); //Сигнал D15 - шина данных АЦП
gpio_direction_input(118); //Сигнал D16 - шина данных АЦП
gpio_direction_input(119); //Сигнал D17 - шина данных АЦП
gpio_direction_input(120); //Сигнал D18 - шина данных АЦП
gpio_direction_input(121); //Сигнал D19 - шина данных АЦП
gpio_direction_input(122); //Сигнал D20 - шина данных АЦП
gpio_direction_input(123); //Сигнал D21 - шина данных АЦП
gpio_direction_input(124); //Сигнал D22 - шина данных АЦП
gpio_direction_input(125); //Сигнал D23 - шина данных АЦП
gpio_direction_input(126); //Сигнал DA - готовность данных АЦП
gpio_direction_input(127); //Сигнал PIN13

gpio_direction_input(133); //Сигнал D0 - шина данных АЦП
gpio_direction_input(134); //Сигнал D1 - шина данных АЦП
gpio_direction_input(135); //Сигнал D2 - шина данных АЦП
gpio_direction_input(136); //Сигнал D3 - шина данных АЦП
gpio_direction_input(137); //Сигнал D4 - шина данных АЦП
gpio_direction_input(138); //Сигнал D5 - шина данных АЦП
gpio_direction_input(139); //Сигнал D6 - шина данных АЦП
gpio_direction_input(140); //Сигнал D7 - шина данных АЦП
gpio_direction_input(141); //Сигнал D8 - шина данных АЦП
gpio_direction_input(142); //Сигнал D9 - шина данных АЦП
gpio_direction_input(143); //Сигнал D10 - шина данных АЦП
gpio_direction_input(144); //Сигнал D11 - шина данных АЦП
gpio_direction_input(145); //Сигнал D12 - шина данных АЦП
gpio_direction_input(146); //Сигнал D13 - шина данных АЦП
gpio_direction_input(147); //Сигнал D14 - шина данных АЦП
gpio_direction_output(154, 0); //Сигнал C_EN_GRAD - разрешение формирования градуировочного сигнала ФЦП
gpio_direction_output(155, 0); //Сигнал C_MP_PP - выбор режима работы ФЦП (периодическая/М - последовательности)
gpio_direction_output(156, 0); //Сигнал C_TYPE_PP - выбор режима работы ФЦП (периодическая с паузой/без паузы)
gpio_direction_output(158, 0); //Сигнал C_SS - запуск формирования цифровых последовательностей ФЦП
gpio_direction_input(159); //Сигнал PIN5

gpio_direction_output(160, 0); //Сигнал CSMP1 - кофициент деления импульсов ГТИ для формирования сигнала Sample ФЦП
gpio_direction_output(161, 0); //Сигнал CSMP2 - кофициент деления импульсов ГТИ для формирования сигнала Sample ФЦП
gpio_direction_output(162, 0); //Сигнал CSMP3 - кофициент деления импульсов ГТИ для формирования сигнала Sample ФЦП
gpio_direction_output(163, 0); //Сигнал CSMP4 - кофициент деления импульсов ГТИ для формирования сигнала Sample ФЦП
gpio_direction_output(164, 0); //Сигнал CSMP5 - кофициент деления импульсов ГТИ для формирования сигнала Sample ФЦП
gpio_direction_output(165, 0); //Сигнал CSMP6 - кофициент деления импульсов ГТИ для формирования сигнала Sample ФЦП

gpio_direction_output(192, 0); //Сигнал CDMP1 - количество дискрет в минимальном импульсе М - последовательности ФЦП
gpio_direction_output(193, 0); //Сигнал CDMP2 - количество дискрет в минимальном импульсе М - последовательности ФЦП
gpio_direction_output(196, 0); //Сигнал CDPP1 - длительность импульса периодической последовательности ФЦП
gpio_direction_output(197, 0); //Сигнал CDPP2 - длительность импульса периодической последовательности ФЦП
gpio_direction_output(198, 0); //Сигнал CDPP3 - длительность импульса периодической последовательности ФЦП
gpio_direction_input(202); //Сигнал PIN14
gpio_direction_input(204); //Сигнал PIN12
}

// Деинициализация портов GPIO для работы с устройствами БУРС
static void gpio_deinitialization()
{
//Деинициализация портов ввода-вывода
iounmap(iomux_base);
release_mem_region(IOMUX_BASE_ADDR, region_size);

iounmap(gpio1_base);
release_mem_region(GPIO1_BASE_ADDR, region_size);

iounmap(gpio2_base);
release_mem_region(GPIO2_BASE_ADDR, region_size);

iounmap(gpio3_base);
release_mem_region(GPIO3_BASE_ADDR, region_size);

iounmap(gpio4_base);
release_mem_region(GPIO4_BASE_ADDR, region_size);

iounmap(gpio5_base);
release_mem_region(GPIO5_BASE_ADDR, region_size);

iounmap(gpio6_base);
release_mem_region(GPIO6_BASE_ADDR, region_size);

iounmap(gpio7_base);
release_mem_region(GPIO7_BASE_ADDR, region_size);

gpio_free(7);
gpio_free(8);
gpio_free(9);

gpio_free(32);
gpio_free(33);
gpio_free(35);
gpio_free(38);
gpio_free(40);
gpio_free(55);
gpio_free(59);
gpio_free(60);

gpio_free(75);
gpio_free(77);
gpio_free(80);
gpio_free(81);
gpio_free(82);
gpio_free(84);
gpio_free(85);
gpio_free(87);
gpio_free(88);
gpio_free(89);
gpio_free(91);
gpio_free(92);
gpio_free(93);

gpio_free(102);
gpio_free(103);
gpio_free(112);
gpio_free(113);
gpio_free(114);
gpio_free(115);
gpio_free(117);
gpio_free(118);
gpio_free(119);
gpio_free(120);
gpio_free(121);
gpio_free(122);
gpio_free(123);
gpio_free(124);
gpio_free(125);
gpio_free(126);
gpio_free(127);

gpio_free(133);
gpio_free(134);
gpio_free(135);
gpio_free(136);
gpio_free(137);
gpio_free(138);
gpio_free(139);
gpio_free(140);
gpio_free(141);
gpio_free(142);
gpio_free(143);
gpio_free(144);
gpio_free(145);
gpio_free(146);
gpio_free(147);
gpio_free(154);
gpio_free(155);
gpio_free(156);
gpio_free(158);
gpio_free(159);

gpio_free(160);
gpio_free(161);
gpio_free(162);
gpio_free(163);
gpio_free(164);
gpio_free(165);

gpio_free(192);
gpio_free(193);
gpio_free(196);
gpio_free(197);
gpio_free(198);
gpio_free(202);
gpio_free(204);
}

void pio_out_port(void * pio, unsigned int val, unsigned int mask)
{
unsigned int oldVal = 0, newVal = 0, newMask=0;

newMask = ~mask;

oldVal = ((*(int*)(pio+GPIO_DR)) & newMask);

newVal = oldVal + (val & mask);

*(int*)(pio+GPIO_DR) = newVal;
}

int pio_in_port(void * pio, unsigned int mask)
{
return ((*(int*)(pio+GPIO_DR)) & mask);

}


// --------- Функции работы с буфером FIFO

//Очистить буфер FIFO
static void ResetFIFOBuffer(void)
{
inputBuffer.start=0;
inputBuffer.end=0;
}

//Добавить данные в буфер FIFO
static void PushFIFOBuffer(void)
{
locked=1;
inputBuffer.data[inputBuffer.end]=(char)(data_adc1);
inputBuffer.end=(inputBuffer.end+1) % INPUT_BUFFER_SIZE;
inputBuffer.data[inputBuffer.end]=(char)(data_adc1>>8);
inputBuffer.end=(inputBuffer.end+1) % INPUT_BUFFER_SIZE;
inputBuffer.data[inputBuffer.end]=(char)(data_adc2);
inputBuffer.end=(inputBuffer.end+1) % INPUT_BUFFER_SIZE;
inputBuffer.data[inputBuffer.end]=(char)(data_adc2>>8);
inputBuffer.end=(inputBuffer.end+1) % INPUT_BUFFER_SIZE;
inputBuffer.data[inputBuffer.end]=(char)(data_st);
inputBuffer.end=(inputBuffer.end+1) % INPUT_BUFFER_SIZE;
inputBuffer.data[inputBuffer.end]=(char)(data_st>>8);
inputBuffer.end=(inputBuffer.end+1) % INPUT_BUFFER_SIZE;
locked=0;
}


// --------- Функции устройства

//Чтение сигнала готовности данных АЦП
static int read_DA()
{
return gpio_get_value(126);
}

//Выбор режима работы БУРС
// regim = 0 - М - последовательность
// regim = 1 - периодическая последовательность с паузой
// regim = 2 - периодическая последовательность без паузы
// regim > 2 - М - последовательность
static void set_regim(int regim)
{
switch(regim)
{
case 0 : {
gpio_set_value(155, 1);
gpio_set_value(156, 0);
break;
}
case 1 : {
gpio_set_value(155, 0);
gpio_set_value(156, 0);
break;
}
case 2 : {
gpio_set_value(155, 0);
gpio_set_value(156, 1);
break;
}
default : {
gpio_set_value(155, 1);
gpio_set_value(156, 0);
}
}
}

//Управление сигналом градуировки
// val = 0 - запретить сигнал градуировки
// val >= 1 - разрешить сигнал градуировки
static void set_grad(int val)
{
if (val==0) gpio_set_value(154, 0);
else gpio_set_value(154, 1);
}

//Выбор длительности импульса периодической последовательности
// val = 0 - 0,04 c.
// val = 1 - 0,08 c.
// val = 2 - 0,16 c.
// val = 3 - 0,32 c.
// val = 4 - 0,64 c.
// val = 5 - 1,28 c.
// val = 6 - 2,56 c.
// val = 7 - 5,12 c.
static void set_CDPP(int val)
{
unsigned int mask=112;
unsigned int value;

value=(val<<4);
pio_out_port(gpio7_base, value, mask);
}

//Выбор количества дискрет в минимальном импульсе М - последовательности
// val = 0 - 2 дискреты
// val = 1 - 4 дискреты
// val = 2 - 8 дискрет
// val >= 3 - 16 дискрет
static void set_CDMP(int val)
{
switch(val)
{
case 0 : {
gpio_set_value(192, 1);
gpio_set_value(193, 1);
break;
}
case 1 : {
gpio_set_value(192, 0);
gpio_set_value(193, 1);
break;
}
case 2 : {
gpio_set_value(192, 1);
gpio_set_value(193, 0);
break;
}
case 3 : {
gpio_set_value(192, 0);
gpio_set_value(193, 0);
break;
}
default : {
gpio_set_value(192, 0);
gpio_set_value(193, 0);
}
}
}

//Выбор количества разрядов M - последовательности
// val = 0 - 11
// val = 1 - 12
// val = 2 - 13
// val >= 3 - 14
static void set_CRMP(int val)
{
unsigned int mask=402653184;
unsigned int value;

value=(val<<27);
pio_out_port(gpio2_base, value, mask);
}

//Выбор коэффициента деления частоты ГТИ для формирования сигнала Sample
// val = 1..4095
static void set_CSMP(int val)
{
unsigned int mask1=63;
unsigned int mask2=983232;

unsigned int value1, value2, value3, value4;

value1=(val & 63);
value2=(val & 192);
value3=(val & 3840)<<8;
value4=(value2 | value3);

pio_out_port(gpio6_base, value1, mask1);
pio_out_port(gpio4_base, value4, mask2);
}

//Запуск ФЦП
static void start_reg()
{
//Разрешить запись следующих данных
//reset_error();
gpio_set_value(9, 1);
do
gd=read_DA();
while (gd!=0);
gpio_set_value(9, 0);
gpio_set_value(158, 1);
}

//Остановка ФЦП
static void stop_reg()
{
gpio_set_value(158, 0);
//print_error();
}

//Калибровка АЦП
static void calibrate_ADC()
{
gpio_set_value(8, 1);
//usleep(1);
gpio_set_value(8, 0);
//usleep(1);
}

//Чтение данных АЦП
static void read_data()
{
unsigned int mask1=1048544;
unsigned int mask2=1071644672;

unsigned int adc1,adc2,st_l,st_h,st_hl;
unsigned int d,d1,d2;

//Установить сигнал AS в 0
gpio_set_value(7, 0);
//Прочитать данные первого АЦП и младьшие биты счетчика
d1=pio_in_port(gpio5_base, mask1);
d1=(d1 >> 5);
d2=pio_in_port(gpio4_base, mask2);
d2=(d2 >> 6);
d=d1+d2;
adc1=(d & 0x0000FFFF);
st_l=(d & 0x00FF0000);
st_l=(st_l >> 16);
//Установить сигнал AS в 1
gpio_set_value(7, 1);
//Прочитать данные второго АЦП и старшие биты счетчика
d1=pio_in_port(gpio5_base, mask1);
d1=(d1 >> 5);
d2=pio_in_port(gpio4_base, mask2);
d2=(d2 >> 6);
d=d1+d2;
adc2=(d & 0x0000FFFF);
st_h=(d & 0x00FF0000);
st_h=(st_h >> 8);
//Данные счетчика
st_hl=st_l+st_h;
//Выходные данные
data_adc1=(unsigned short int)adc1;
data_adc2=(unsigned short int)adc2;
data_st=(unsigned short int)st_hl;
//Разрешить запись следующих данных
gpio_set_value(9, 1);
do
gd=read_DA();
while (gd!=0);
gpio_set_value(9, 0);
}

//Чтение кнопок
static int read_key()
{
unsigned int mask=1001390080;
unsigned int d, d1, d2, d3;
int button;

d=pio_in_port(gpio3_base, mask);
d1=d;
d2=d;
d3=d;
d1=((d1>>20) & 3);
d2=((d2>>21) & 28);
d3=((d3>>22) & 224);
d=d1+d2+d3;
button=d;
return button;
}

// Конфигурирование BBS
static void ConfigureBBS(void)
{
stop_reg(); //Запретить генерацию ФЦП
gpio_set_value(9, 1);
gpio_set_value(9, 0);
calibrate_ADC(); //Калибровка АЦП

//Задать режим регистрации
set_regim(command.regim);
set_grad(command.grad);
set_CDPP(command.cdpp);
set_CDMP(command.cdmp);
set_CRMP(command.crmp);
set_CSMP(command.csmp);
}

// --------- Функции драйвера

// Функция загрузки модуля
static int __init bbs_init( void )
{
printk( KERN_ALERT "bbs driver: configuring \n" );
gpio_initialization();
//Задать режим регистрации
command.regim=1;
command.grad=0;
command.cdpp=0;
command.cdmp=0;
command.crmp=0;
command.csmp=320;
command.samples=0;
ConfigureBBS();
printk( KERN_ALERT "bbs driver: driver loaded!\n" );

// Регистрируем устройство и получаем старший номер устройства
major_number = register_chrdev( 0, DEVICE_NAME, &fops );
if ( major_number < 0 )
{
printk( "bbs driver: Registering the character device failed with %d\n", major_number );
return major_number;
}

// Сообщаем присвоенный нам старший номер устройства
printk( "bbs driver: bbs module is loaded!\n" );
printk( "bbs driver: Please, create a dev file with 'mknod /dev/bbs c %d 0'.\n", major_number );

return SUCCESS;
}


// Функция выгрузки модуля
static void __exit bbs_exit( void )
{
// Освобождаем устройство
gpio_deinitialization();

unregister_chrdev( major_number, DEVICE_NAME );
printk( KERN_ALERT "bbs driver: bbs module is unloaded!\n" );
}

// Указываем функции загрузки и выгрузки
module_init( bbs_init );
module_exit( bbs_exit );


// Обработчик прерывания
static irqreturn_t irq_handler(int irq, void *dummy, struct pt_regs * regs)
{
read_data();
PushFIFOBuffer();
samples--;
//e_irq++;
//gpio_set_value(77,1);
//gpio_set_value(77,0);
if (samples==0) stop_reg();

return IRQ_HANDLED;

}

// Открыть устройство
static int device_open( struct inode *inode, struct file *file )
{
int status = 0;
st1=0;
st2=0;
flag=0;
locked=0;
if ( is_device_open ) return -EBUSY;
ResetFIFOBuffer();

printk("bbs driver: Requesting interrupt\n");
//status = request_irq(IRQ_NUMB, irq_handler,0,DEVICE_NAME, NULL);
//status = request_irq(gpio_to_irq(40), irq_handler,IRQF_DISABLED | IRQF_TRIGGER_RISING,DEVICE_NAME, NULL);

status = request_irq(gpio_to_irq(126), irq_handler,IRQF_PROBE_SHARED | IRQF_PERCPU | IRQF_NO_SUSPEND | IRQF_TRIGGER_RISING,DEVICE_NAME , NULL);
set_irq_type(gpio_to_irq(126), IRQ_TYPE_EDGE_RISING);
if (status == 0)
{
printk("bbs driver: bbs IRQ %d request successful!\n",gpio_to_irq(126));

}
else
{
printk("bbs driver: bbs IRQ request failed!\n");
return status;
}
printk("bbs driver: Open device\n");
is_device_open++;

return SUCCESS;
}

// Закрыть устройство
static int device_release( struct inode *inode, struct file *file )
{
is_device_open--;
printk ("bbs driver: bbs irq freed\n");
free_irq(gpio_to_irq(126), NULL);
stop_reg();
ResetFIFOBuffer();

return SUCCESS;
}

// Запись в устройство
static ssize_t device_write( struct file *filp, const char *buff, size_t len, loff_t * off )
{
struct inode* inode;
int count=len;
unsigned char *byte=kmalloc(sizeof(struct dev_command),GFP_KERNEL);
struct dev_state *dev_state;
//Прочитать данные
inode=filp->f_dentry->d_inode;
dev_state=&state[MINOR(inode->i_rdev)];
int st=0;
while (count--)
{
get_user(byte[st],buff);
buff++;
st++;
}
dev_state->byte_write+=len;
//Обработка данных
command.command=byte[0];
command.regim=*((int*)(byte+1));
command.grad=*((int*)(byte+5));
command.cdpp=*((int*)(byte+9));
command.cdmp=*((int*)(byte+13));
command.crmp=*((int*)(byte+17));
command.csmp=*((int*)(byte+21));
command.samples=*((unsigned int*)(byte+25));
//Обработка комманд
switch (command.command)
{
case 'B' : {
stop_reg();
ConfigureBBS();
ResetFIFOBuffer();
samples=command.samples;
start_reg();
break;
}
case 'E' : {
stop_reg();
break;
}
}

printk("command %c \n",command.command);
printk("regim %d \n",command.regim);
printk("grad %d \n",command.grad);
printk("cdpp %d \n",command.cdpp);
printk("cdmp %d \n",command.cdmp);
printk("crmp %d \n",command.crmp);
printk("csmp %d \n",command.csmp);
printk("samples %d \n",command.samples);

//Выход
kfree(byte);
return len;
}

// Чтение из устройства
static ssize_t device_read( struct file *filp, char *buff, size_t len, loff_t * offset )
{
#define MAX_FAILED_OPS 128 //Максимальное колличество блокировок для одной операции чтения

struct inode* inode;
int count=len;
unsigned char byte;
struct dev_state *dev_state;
int failedOps=0;
int st=0;
//Количество элементов в буфере
int curBufferLoad=(inputBuffer.end>=inputBuffer.start) ? (inputBuffer.end-inputBuffer.start) : (INPUT_BUFFER_SIZE-inputBuffer.start+inputBuffer.start);
if (curBufferLoad<len) count=0; //{count=0; e_buf++;}
//Отправить данные
inode=filp->f_dentry->d_inode;
dev_state=&state[MINOR(inode->i_rdev)];
while (count--)
{
//Если работает обработчик прерывания
if (locked)
{
failedOps++;
//e_locked++;
if (failedOps>MAX_FAILED_OPS) break;
else continue;
}
//Если буфер пуст
if (inputBuffer.start==inputBuffer.end) break; //{e_free_buf++; break;}
//Вывод данных
byte=(unsigned char)(inputBuffer.data[inputBuffer.start]);
inputBuffer.start=(inputBuffer.start+1)%INPUT_BUFFER_SIZE;
put_user(byte,buff);
buff++;
st++;
}
dev_state->byte_read+=st;
//Выход
return st;
}
Спуститься к концу Подняться к началу
Персональная информация
dx
Добавлено 08.07.2013 08:53 Сообщение: 2
dx
3.5

Пункты: 7618
Регистрация: 26.10.2010
Пол: Мужчина
Из: Ukraine, Kiev city
Linux != real time
Спуститься к концу Подняться к началу
Персональная информация
Jury093
Добавлено 08.07.2013 12:21 Сообщение: 3
Jury093
4.5

Пункты: 54271
Регистрация: 25.05.2009
Пол: Мужчина
Из: Санкт-Петербург
попробуйте рассмотреть следующее:
- оптимизировать формирование псевдошины - собрать биты последовально и в одном регистре, чтобы работать хотя бы на уровне байтов
- рассмотреть работу через SPI шину на регистр-защелку - защелкиваете данные и быстро по SPI выгоняете их в АРМ
- самое просто но ненадежное - повысить приоритет своей софтины - чревато глюками и зависаниями ОС..
- на этой плате параллельных интерфейсов наружу вроде нет, так бы можно было АЦП привесить и попробовать работать с ней, как со статической памятью..

На любой вопрос есть любой ответ.
Спуститься к концу Подняться к началу
Персональная информация
voland
Добавлено 09.07.2013 11:24 Сообщение: 4
voland
0

Пункты: 1239
Регистрация: 02.04.2011
Большое спасибо за ответы.

Но дело в следующем:

1. Само прерывание вполне успевает отработать.
2. Судя по относительной стабильности количества и времени чередования пропусков, одно (или несколько) устройств с периодичностью 0,1 сек блокируют мое прерывание на 30 мкс что при тактовой частоте 51200 эквивалентно 16-17 пропускам.

Обнаружить что за устройство пока не могу да и не факт что его можно безопасно отключить. Вопрос - как повысить приоритет моего драйвера (или только прерывания) в системе (желательно из драйвера) ??? Cеансы регистрации планируються не более 10 мин. и если на это время система подвиснет то ни чего страшного.

P.S. SPI конечно попробую но если у него приоритет на прерывании такой-же то проблемма в принципе может остаться.

Заранее спасибо!
Спуститься к концу Подняться к началу
Персональная информация
Форум » starterkit.ru » Отладочные платы » SK-iMX53