Ник:
Пароль:

Контакты

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

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

User Info


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

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

Ник:
Пароль:

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

ОбновитьПодробнееВсегоВсего:7
Форум » starterkit.ru » Embedded Linux
DMA - попытки адаптировать CSPI (imx53) на работу без прерываний
buletz
Добавлено 22.03.2013 18:20 Редактировалось 22.03.2013 18:21
0
Сообщение: 1
buletz
3

Пункты: 5920
Регистрация: 16.11.2011
Пол: Мужчина
начало было тут:
http://www.starterkit.ru/html/index.php?name=forum&op=view&id=19221

Суть:
Есть девайс который непрерывно шлет данные по SPI на линукс-плату (девайс - мастер, линукс - слейв), а на линуксе нужно эти данные принять.
Есть самописный драйвер для работы с SPI, который через прерывания работает ОК. Однако, учитывая, что прерывания нагружают проц, требуется перейти на DMA, чтобы перенос данных из FIFO буфера SPI проводился без отвлечения процессора.

Проблема:
я скопипастил с небольшими коррекциями все, что касается инициализации DMA из mxc_uart.c, который шел вместе со стартеркитным ядром 2.6.35. Вот получившийся исходник моего драйвера:
http://pastebin.com/0Jj4hGVc

В итоге имею, что read callback не вызывается вообще.
А счетчик байт в буфере FIFO (SPI) все время остается на максимуме (64 б), т.е. выходит что он вообще никогда не опустошается, а следовательно DMA не выполняет свою обязанность - переносить из FIFO в заданную область памяти (буфер).

Вопросы:
1. Правильно я понимаю, что прерывания самого SPI можно отключить, т.к. для работы DMA они не нужны ?
2. Почему не вызывается callback ?
3. Есть ли какие-то утилитки, которыми можно посмотреть чем занимается DMA и какие на него повешены устройства?
Спуститься к концу Подняться к началу
Персональная информация
leh
Добавлено 22.03.2013 23:34 Сообщение: 2
leh
5

Пункты: 1646
Регистрация: 07.06.2009
Пол: Мужчина
Из: Волгоград
Цитата
1. Правильно я понимаю, что прерывания самого SPI можно отключить, т.к. для работы DMA они не нужны ?

Да, прерывания от самого SPI не нужны для работы через DMA. Надо вместо этого разрешить запрос DMA, когда FIFO будет на грани заполнения. Как я понял, у вас это сделано.
Цитата
2. Почему не вызывается callback ?

У меня есть предположение: что если вы выбрали не тот канал DMA? В dma.h определены вроде такие каналы:
Код

MXC_DMA_CSPI1_RX,
MXC_DMA_CSPI1_TX,
MXC_DMA_CSPI2_RX,
MXC_DMA_CSPI2_TX,
MXC_DMA_CSPI3_RX,
MXC_DMA_CSPI3_TX,

Как я понял, в контроллере один модуль CSPI (MXC_DMA_CSPI1?) и 2 модуля ECSPI (MXC_DMA_CSPI2 и MXC_DMA_CSPI3?). Так что может вам попробовать канал MXC_DMA_CSPI3?
Кстати при формировании такого типа канала (конкретный модуль периферии -> память) указывать src_addr насколько я понял необязательно, т.к. он уже задан при выборе канала.
Цитата
3. Есть ли какие-то утилитки, которыми можно посмотреть чем занимается DMA и какие на него повешены устройства?

По-моему в /proc/interrupts можно видеть только общее количество прерываний от SDMA, соотвественно от всех модулей, что через него работают.
Я делал собственный драйвер для SSI и по /proc/interrupts прикидывал количество прерываний в секунду от ПДП.
Спуститься к концу Подняться к началу
Персональная информация
buletz
Добавлено 25.03.2013 11:53 Редактировалось 25.03.2013 12:11 Сообщение: 3
buletz
3

Пункты: 5920
Регистрация: 16.11.2011
Пол: Мужчина
UDPATED on Mar 25, 13:05.

Цитата

У меня есть предположение: что если вы выбрали не тот канал DMA? ...
Как я понял, в контроллере один модуль CSPI (MXC_DMA_CSPI1?) и 2 модуля ECSPI (MXC_DMA_CSPI2 и MXC_DMA_CSPI3?). Так что может вам попробовать канал MXC_DMA_CSPI3?


Проверил - канал вроде верный, проверял так:

mx5x.h
/arch/arm/plat-mxc/include/mach/mx5x.h

Код
#define CSPI2_BASE_ADDR (AIPS2_BASE_ADDR + 0x000AC000)

Согласно мануалу физический адрес ECSPI2 в mx53 это 63FAC000, поэтому окончание адреса как раз совпадает.

И далее, сами идентификаторы каналов в том же h файле:
Код
/*
* DMA request assignments
*/
#define DMA_REQ_CSPI2_TX 9
#define DMA_REQ_CSPI2_RX 8

Это соответствует ECSPI-2 согласно мануалу, табл. 3-2 (SDMA Event mapping):
8 - ECSPI-2 - DMA Rx request
9 - ECSPI-2 - DMA Tx request

=========
По умолчанию в ядре не предусмотрен канал DMA RX для SPI.
Поэтому я делал небольшую правку ядра, чтобы добавить этот канал, а именно:

dma.c
/arch/arm/mach-mx5/dma.c
содержит структуру:
Код
static mxc_sdma_info_entry_t mxc_sdma_active_dma_info[] = {
{MXC_DMA_UART1_RX, &mxc_sdma_uart1_rx_params},
{MXC_DMA_UART1_TX, &mxc_sdma_uart1_tx_params},
.. и т.д.

Каналов для SPI RX вообще нет, я добавил:
Код
{MXC_DMA_CSPI2_RX, &mxc_sdma_cspi2_rx_params}, // added by Alexeev


плюс в этом же файле добавил описание структуры, на которую ссылается канал:
Код
//added by Alexeev
static mxc_sdma_channel_params_t mxc_sdma_cspi2_rx_params = {
.chnl_params = {
.watermark_level = 32,
.per_address = CSPI2_BASE_ADDR + 0x00,
.peripheral_type = CSPI,
.transfer_type = emi_2_per,
.event_id = DMA_REQ_CSPI2_RX,
.bd_number = 16,
.word_size = TRANSFER_32BIT,
},
.channel_num = MXC_DMA_CHANNEL_CSPI2_RX,
.chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
};
Спуститься к концу Подняться к началу
Персональная информация
buletz
Добавлено 25.03.2013 14:32 Сообщение: 4
buletz
3

Пункты: 5920
Регистрация: 16.11.2011
Пол: Мужчина
1. Нашел у себя небольшую ошибку в настройке DMА, исправление которой, впрочем, не помогло.

/arch/arm/mach-mx5/dma.c

Код
static mxc_sdma_channel_params_t mxc_sdma_cspi2_rx_params = {
...
.transfer_type = per_2_emi,
...
};

(до этого было ошибочно emi_2_per, хотя нужно направление "периферия->память")

2. Начал копать SDMA и наткнулся на следующую проблему.

Не могу понять каким образом скрипты SDMA определяют с какого адреса в какой сливать.
Насколько я вижу, эти скрипты описаны в файле
/arch/arm/mach-mx5/sdma_script_code_mx53.h


Код
/*!
* Returns pc of SDMA script according to peripheral and transfer type
*
* @param peripheral_type peripheral type
* @param transfer_type transfer type
*
* @return PC of SDMA script
*/
static unsigned short sdma_get_pc(sdma_periphT peripheral_type,
sdma_transferT transfer_type)
...
else if (peripheral_type == CSPI || peripheral_type == EXT ||
peripheral_type == SSI) {

switch (transfer_type) {
case per_2_emi:
res = sdma_script_addrs.mxc_sdma_app_2_mcu_addr;
break;
...
{


Из кода выше видно, что для SPI используется адрес sdma_script_addrs.mxc_sdma_app_2_mcu_addr

который в свою очередь равен некому "загадочному" числу 683:
Код
#define app_2_mcu_ADDR_MX53 683

также указан размер (скрипта?)
Код
#define app_2_mcu_SIZE_MX53 64


Полагаю, что 683 это номер байта в бинарном коде, откуда начинается скрипт. Данный бинарный код приведен в том же файле:
Код
static const short sdma_code_mx53[] = {
0xc1e3, 0x57db, 0x5fe3, 0x57e3, 0x52f3, 0x6a01, 0x008f, 0x00d5,
...


И вот квинт-эссенция проблемы:

Как понять работу этого SDMA скрипта - неужто надо заниматься реверс-инжениренгом и деассемблировать эту последовательность? ...

PS. Как же фрискейловцы намудрили то всё...
Спуститься к концу Подняться к началу
Персональная информация
Форум » starterkit.ru » Embedded Linux