реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Разделение ресурса, под ucOS-II
prottoss
сообщение Feb 6 2008, 08:48
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Всем привет!

Такая вот проблемка. Есть железный SPI0 на AT91SAM7X. По этому интерфейу подключено два устройства, каждое устройство обслуживается своей задачей. Написал вот такой код для обращения к SPI:

Код
SPI_RESULT SPI_Xfer(SPI_XDesc_t *desc)
{

/* Check valid device number */
   if(g_DevCnt <= desc->dev_idx)
        return SPI_RES_INVALID_DEVICE_INDEX;

/* Get desc & interface */
SPI_CS_DESC *cs = &g_SPI_CS[desc->dev_idx];
AT91PS_SPI spi = cs->spi;

/* Wait for SPI unlocked */
UINT8 os_err;
OSFlagPend(g_SPI_Events, cs->locked,
      OS_FLAG_WAIT_SET_ANY | OS_FLAG_CONSUME, SPI_XFER_TIMEOUT, &os_err);



/* Interface is locked. Select device */



................................................................................
.........................


    /* Unlock interface & return OK */
OSFlagPost(g_SPI_Events, cs->locked, OS_FLAG_SET, &os_err);
return SPI_RES_OK;

}


Поясню идею. Создан флаг блокировки интерфейса. Когда он установлен - интерфейс не блокирован, но при выходе из функции OSFlagPend он автоматически обнуляется, тем самым блокируя интерфейс для всех остальных задач. При выходе из функции передачи SPI_Xfer(...) флаг блокировки опять устанавливется, тем самым разрешая другой задаче работать с интерфейсом...

Вот только что-то не совсем все это работает. Кто знает, поясните, где я ошибаюсь.


--------------------
Go to the top of the page
 
+Quote Post
ig_z
сообщение Feb 6 2008, 08:56
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 437
Регистрация: 27-08-04
Пользователь №: 551



Так для этого в явном виде есть мютекс. Почему его не применяете?
Go to the top of the page
 
+Quote Post
prottoss
сообщение Feb 6 2008, 08:59
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(ig_z @ Feb 6 2008, 15:56) *
Так для этого в явном виде есть мютекс. Почему его не применяете?
Не хочу применять мютекс, потому как потом все будет портировано не другую ОСь - в этой удобно отлаживать - я работаю в ИАРе. Мне интересно - почему не работает в моем случае


--------------------
Go to the top of the page
 
+Quote Post
yuri_t
сообщение Feb 6 2008, 15:53
Сообщение #4


Частый гость
**

Группа: Свой
Сообщений: 163
Регистрация: 24-08-05
Пользователь №: 7 937



В этом случае лучше использовать семафор - он как раз под такие вещи и придуман(и переносимость
будет полная).
Go to the top of the page
 
+Quote Post
ig_z
сообщение Feb 6 2008, 16:45
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 437
Регистрация: 27-08-04
Пользователь №: 551



Цитата(yuri_t @ Feb 6 2008, 19:53) *
В этом случае лучше использовать семафор - он как раз под такие вещи и придуман(и переносимость
будет полная).

Можно только добавить, что семафор д.б. бинарный или же, за отсутствием такового, - счетный, проиниченый начальным значением 1. Собс-но для краткости эту кухню и называют мютексом smile.gif .
Go to the top of the page
 
+Quote Post
AndrewN
сообщение Feb 7 2008, 14:11
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 336
Регистрация: 7-03-07
Из: Петербург
Пользователь №: 25 961



Цитата(prottoss @ Feb 6 2008, 11:48) *
Такая вот проблемка. Есть железный SPI0 на AT91SAM7X. По этому интерфейу подключено два устройства, каждое устройство обслуживается своей задачей. Написал вот такой код для обращения к SPI:

Код
code snipped


Поясню идею. Создан флаг блокировки интерфейса. Когда он установлен - интерфейс не блокирован, но при выходе из функции OSFlagPend он автоматически обнуляется, тем самым блокируя интерфейс для всех остальных задач. При выходе из функции передачи SPI_Xfer(...) флаг блокировки опять устанавливется, тем самым разрешая другой задаче работать с интерфейсом...

Вот только что-то не совсем все это работает. Кто знает, поясните, где я ошибаюсь.

Я думаю, что в логике - в программном протоколе или алгоритме. Логическая схема
обмена (на мой взгляд, поскольку я не знаю деталей) может выглядеть так:

Код
TASK0     TASK1
  |         |
  \         /
   \       /
    \     /
     \   /
      \ /
       |
     DRIVER
       |
       |
  PHY IF (SPI0)
  |         |
  |         |
DEV0      DEV1


следовательно, требуется два мьютекса.

Если учесть что IF последовательный и устройства могут его использовать только
попеременно, то можно обойтись одним мьютексом (или флагом события, что эквивалентно)
и одной условной переменной, т.е. адресом устройства в SPI - в *одной* задаче.

HTH
Go to the top of the page
 
+Quote Post
prottoss
сообщение Feb 7 2008, 15:06
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(AndrewN @ Feb 7 2008, 21:11) *
Я думаю, что в логике - в программном протоколе или алгоритме. Логическая схема обмена (на мой взгляд, поскольку я не знаю деталей) может выглядеть так:
Так как Вы нарисовали, так и есть - есть несколько задач, пытающихся использовать интерфейс, есть флаг захвата интерфейса - который ждут задачи, что бы его использовать... Зачем тока ДВА аж мьютекса? А если у меня будет 32 задачи???


--------------------
Go to the top of the page
 
+Quote Post
AndrewN
сообщение Feb 8 2008, 17:51
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 336
Регистрация: 7-03-07
Из: Петербург
Пользователь №: 25 961



Цитата(prottoss @ Feb 7 2008, 18:06) *
Так как Вы нарисовали, так и есть - есть несколько задач, пытающихся использовать интерфейс, есть флаг захвата интерфейса - который ждут задачи, что бы его использовать... Зачем тока ДВА аж мьютекса? А если у меня будет 32 задачи???


В самом общем виде:

N задач ожидают ввода от N устройств, все N устройств обслуживает один драйвер. Каждая задача имеет свой собственный FIFO входящих пакетов и ждет свой собственный семафор. Драйвер, получив очередной пакет данных, анализирует адрес устройства, помещает пакет в соотвествующий FIFO и инкрементирует соотвествующий семафор. Соотвествующая семафору задача забирает пакет из своего FIFO, обрабатывает его и снова становится в ожидание семафора или забирает следующий пакет, пока не обработает весь FIFO. А если все N задач ждут один семафор или мьютекс, то пакеты просто перепутаются между задачами.

Второй метод использует тот факт, что устройства на SPI могут захватывать шину только последовательно. Тогда одна задача может обрабатывать все N устройств. Задача ждет один семафор от драйвера. Драйвер, получив очередной пакет данных, помещает адрес и пакет в единственный FIFO и инкрементирует семафор. Задача принимает из FIFO адрес и пакет и передает управление в ветвь, соотвествующюю адресу (или номеру) устройства. Это хорошо известная модель - суперцикл, но с ожиданием семафора.

Передача пакета из задачи в устройство (вывод) тоже использует FIFO, адрес и семафор. Драйвер ждет семафор и инициирует передачу пакетов, пока не обнулит FIFO. Так как драйвер один, то и FIFO и семафор будут в единственном числе, все N задач пишут в одно и тоже FIFO, и запись должна быть защищена мьютексом.

HTH
Go to the top of the page
 
+Quote Post
prottoss
сообщение Feb 8 2008, 18:45
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(AndrewN @ Feb 9 2008, 00:51) *
У меня не используется FIFO ни в драйвере SPI, ни в задачах при работе с SPI, потому как ограниченный ресурс памяти. Объем данных, перекачиваемый за одно обращение к IF относительно большой. То что вы сказали выше, мне знакомо, но, в проекте, который сейчас у меня в работе, это не применимо. Все задачи работают с интерфейсом SPI по принципу - "кто успел, тот присел". Драйвер ничего не выбирает и ничего не ставит в очередь.

PS: ошибку я нашел. Так как это мой первый проект на ARM, было недопонимание по поводу прерываний от SPI smile.gif В данный момент все устаканилось. По одному драйверу работают 4 задачи на 2 интерфейса SPI(0 и 1). В ucOS-II используется один OS_FLAG_GRP. Два флажка на прерывания, два на блокирование соответствующего интерфейса.


--------------------
Go to the top of the page
 
+Quote Post
Chudik
сообщение Feb 24 2008, 07:24
Сообщение #10


Частый гость
**

Группа: Свой
Сообщений: 197
Регистрация: 31-03-06
Пользователь №: 15 676



Я понимаю, что решение найдено. Но я бы повесил очередь запросов (queue). Каждая задача кидает туда номер SPI + указатель на данные. А драйвер считывает очередной запрос и кидает данные из указанной памяти в указанный порт.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Feb 24 2008, 08:20
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Chudik @ Feb 24 2008, 10:24) *
Но я бы повесил очередь запросов (queue)....

В очень многих случаях это (или другие варианты использования очередей) действительно очень хороший вариант.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
sonycman
сообщение Aug 8 2010, 13:17
Сообщение #12


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(Chudik @ Feb 24 2008, 11:24) *
Но я бы повесил очередь запросов (queue). Каждая задача кидает туда номер SPI + указатель на данные. А драйвер считывает очередной запрос и кидает данные из указанной памяти в указанный порт.

Но тут проблема с указателем на данные - процесс, записавший указатель в очередь, должен хранить сами данные до тех пор, пока драйвер их не передаст.

Весьма не удобно sad.gif

Если записывать в очередь не указатель, а непосредственно сами данные - такой проблемы нет, но тогда нужно иметь много памяти для того, чтобы все данные влезли в очередь...
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 7th July 2025 - 23:21
Рейтинг@Mail.ru


Страница сгенерированна за 0.01466 секунд с 7
ELECTRONIX ©2004-2016