Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Разделение ресурса
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы
prottoss
Всем привет!

Такая вот проблемка. Есть железный 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(...) флаг блокировки опять устанавливется, тем самым разрешая другой задаче работать с интерфейсом...

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

Можно только добавить, что семафор д.б. бинарный или же, за отсутствием такового, - счетный, проиниченый начальным значением 1. Собс-но для краткости эту кухню и называют мютексом smile.gif .
AndrewN
Цитата(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
prottoss
Цитата(AndrewN @ Feb 7 2008, 21:11) *
Я думаю, что в логике - в программном протоколе или алгоритме. Логическая схема обмена (на мой взгляд, поскольку я не знаю деталей) может выглядеть так:
Так как Вы нарисовали, так и есть - есть несколько задач, пытающихся использовать интерфейс, есть флаг захвата интерфейса - который ждут задачи, что бы его использовать... Зачем тока ДВА аж мьютекса? А если у меня будет 32 задачи???
AndrewN
Цитата(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
prottoss
Цитата(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. Два флажка на прерывания, два на блокирование соответствующего интерфейса.
Chudik
Я понимаю, что решение найдено. Но я бы повесил очередь запросов (queue). Каждая задача кидает туда номер SPI + указатель на данные. А драйвер считывает очередной запрос и кидает данные из указанной памяти в указанный порт.
zltigo
Цитата(Chudik @ Feb 24 2008, 10:24) *
Но я бы повесил очередь запросов (queue)....

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

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

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

Если записывать в очередь не указатель, а непосредственно сами данные - такой проблемы нет, но тогда нужно иметь много памяти для того, чтобы все данные влезли в очередь...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.