KA3AKOB
Пользователь
Сообщений: 55
|
|
« : 12 Апрель, 2019, 16:59:09 » |
|
Разрабатывается специфическая плата для процессоров CPC304 под QNX6.4. Для неё пишу Resource Manager. Алгоритм передачи вкратце таков: в пользовательской программе осуществляется вызов функции write(fd, buf, n); Эти n байтов надо записать в плату по прерыванию на каждый байт. Прерывание выставляется на шину ISA и обрабатывается обработчиком прерывания ISR(). После записи последнего байта ISR() должен выдать команду на выполнение массовой операции в плате над всеми байтами и по завершении этой операции в плате получить прерывание от платы, обработать его и завершить операцию записи. Насколько я понимаю выполняется это так: вызов write(fd, buf, n); преобразуется библиотекой менеджеров ресурсов в MsgSend(), происходит передиспетчеризация потоков и когда-нибудь получит управление поток менеджера ресурсов и библиотека вызовет callback-функцию io_write() в менеджере. io_write скопирует данные из msg в буфер доступный io_write() и ISR(), выдаст командой out8(addr, myByte) первый байт в плату и должен затормозиться до окончания передачи всех байтов, то есть: обработки всех прерываний от платы. ISR() должен подсчитывать передаваемые в плату байты и по окончании приёма последнего из них выдать в плату команду на массовую обработку всех байтов. По окончании этой обработки придёт прерывание от платы и тогда ISR() должен сделать что-то такое, чтобы io_write() растормозился и завершил работу. Ну, то есть вернулся в библиотечную функцию, а та уж сама сформирует MsgReply(). А по MsgReply() растормозится write(fd, buf, n); в клиентской программе. Согласно Кртену, если обработчик прерывания не хочет вызывать передиспетчеризацию потоков, то он возвращает (const struct sigevent *)NULL, а если надо возбудить передиспетчеризацию, то не NULL. Вопрос что? В псевдокоде то, что хочу получить:
int io_write (resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *ocb) { // скопировать msg в буфер доступный и io_write() и ISR() // передать первый байт в плату out8(addr, myByte); // затормозиться до окончания обработки всех прерываний // выполнить завершающие действия return (_RESMGR_NPARTS (0)); // операция записи выполнена. };
const struct sigevent * Td04Driver::main_isr (void *arg, int id) { if (i<n) { // обработаны не все байты out8(addr, myByte); return ((struct sigevent *)NULL); // не возбуждать передиспетчеризацию } else { // обработаны все байты // что-то ещё сделать return ((struct sigevent *)что_такое_надо_вернуть); // возбуждать передиспетчеризацию } }
Как известно из того же Кртена обработчик прерывания не может вызывать любые системные функции, а только очень ограниченный набор, типа InterruptMask(). Мне надо, чтобы по окончанию всех прерываний растормозился поток менеджера ресурсов и именно там где заторможен был в io_wite(), а не все какие есть потоки в системе. И мне надо, чтобы поток менеджера ресурсов не вернулся раньше завершения всех прерываний в пользовательскую программу с write().
|