|
Виж темите без отговор | Виж активните теми
Дата и час: Пон Юли 27, 2026 3:31 pm
Въпрос относно собствена библиотека за pic32mx
| Автор |
Съобщение |
|
Zdrav
Ранг: Форумен бог
Регистриран на: Сря Яну 26, 2005 2:01 pm Мнения: 1952 Местоположение: Варна
|
 Re: Въпрос относно собствена библиотека за pic32mx
Миро, това което си прочел между редовете е нещо което е било вече в твоята глава. Не ставаше въпрос за неефективност на драйвери и ОС по време на изпълнение на програмата (run-time). Пак повтарям не съм искал да кажа това. Това което искам просто да отбележа е че структирирането на софтуера, архитектурата, дизайна или както там го наричаме, ако е основан на примитиви моделиращи апаратната част/хардуера, е неефективен метод по време на проектирането на софтуера (design time). имхо
_________________ Най-опасният враг на истината и свободата е мнозинството.
|
| Пон Фев 10, 2020 12:34 pm |
|
 |
|
miro_atc
Ранг: Форумен бог
Регистриран на: Нед Фев 26, 2006 6:52 pm Мнения: 11266 Местоположение: Добрич
|
 Re: Въпрос относно собствена библиотека за pic32mx
Значи не съм те разбрал, ама и сега не те разбирам... "примитиви моделиращи апаратната част" не го схващам. За мен примитивите са решения на проблем. Имаш проблем, ползваш решение. Нямаш проблем, не ползваш....
|
| Пон Фев 10, 2020 1:23 pm |
|
 |
|
Zdrav
Ранг: Форумен бог
Регистриран на: Сря Яну 26, 2005 2:01 pm Мнения: 1952 Местоположение: Варна
|
 Re: Въпрос относно собствена библиотека за pic32mx
Тези примитиви обособени ли са? Лесни ли са за повторна употреба? Ако отговорът е - Да. Значи лесно ще ме разбереш. Имаме ли "библиотеки" от опашки и FIFO-та или имаме spi.c uart.c adc.c и т.н. "драйвери". Ако отговорът е -да, значи фокусът е изместен върху апаратната част. Ето и примера от по-горе как би изглеждал: един "драйвер" трябва да му е все тая, колко "клиента" го ползват стига да има опашка или арбитър/диспатчър... който да се грижи за това да не стават конфликти и омазвания. Сигурен съм, че ти например имаш решения за такива елементарни проблеми, но те обособени ли са(в отделен файл)? Имат ли ясно дефинирани интерфейси така че да можеш да ги преизползваш? Ако всичко това е така, защо няма нито една тема за такива примитиви. А итерациите на тема "драйвери" и ОС с лопата да ги ринеш. Риторичен въпрос естествено, само за да изясним къде е фокуса.
_________________ Най-опасният враг на истината и свободата е мнозинството.
|
| Пон Фев 10, 2020 2:49 pm |
|
 |
|
miro_atc
Ранг: Форумен бог
Регистриран на: Нед Фев 26, 2006 6:52 pm Мнения: 11266 Местоположение: Добрич
|
 Re: Въпрос относно собствена библиотека за pic32mx
Аз мисля, че едното няма връзка с другото. Нормално е кодът за фифо да е да кажем в fifo.c а пък кодът за uart да е в uart.c. Подобна капсулация винаги е за предпочитане пред пръскането по десетки файлове без каквато и да е логика или пък по някаква извратена логика  Въпросът беше как би трябвало да изглежда един uart.c. Че вътре ще е код за uart е ясно, но дали този код ще създава някакъв интерфейс и дали този интерфейс ще бъде абстрактен или не. И ако е абстрактен колко абстрактен - дали ще се абстрахираме само от модела на уарт-а или генерално ще се абстрахираме от това че е уарт изобщо. При ОС обикновено абстракцията е по-голяма. Примерно по-горе вълшебникът даде код, който вика четене. Абстрактно четене. Една и съща функция се вика, независимо дали четеш от uart, spi или нещо друго. Откъде четеш е подробност, която може и да не те интересува. Демек едно параметърче, което идва от някъде и ти го препредаваш и не ти пука. Няма нужда да инклудваш uart.h или spi.h или каквото там физически е отдолу, ако това не те вълнува. Също така може и да не те вълнува дали се ползва ДМА, дали има буфериране с фифо и т.н. Не знам това ли имаш предвид "пенкилер"... но ако е това, по-добро от него аз не познавам  А пък HAL-a e нещо, което се среща само в най-големите системи, когато драйверите са доста сложни или има разделяне някакво. При малките може би само за етернет или usb или друг такъв стек има смисъл от HAL, за да не пренаписваш целия стек всеки път. Докато uart, spi и т.н. обикновено си се пренаписват и няма нужда от по-специална абстракция.
|
| Пон Фев 10, 2020 4:17 pm |
|
 |
|
gicho
Ранг: Форумен бог
Регистриран на: Пон Мар 13, 2006 1:59 pm Мнения: 3867 Местоположение: Габрово
|
 Re: Въпрос относно собствена библиотека за pic32mx
Тук има разлика в подходите, и тя води до принципно различни решения - за да имаш "параметърче" то трябва да има дефиниран тип и да го получиш. Казваш, "препредаваш и не ти пука" - т.е. не го ползваш за нищо твое, а препредаваш за да угодиш на някаква идея как се изгражда поток или процес от обработка. Връзката между отделните нива или слоеве в т.нар. от теб "ОС подход" изисква всеки слой да включи в себе си начин за свързване. Примерно "handle.h", или "transport.h" и т.н. В единия случай (подход) тия типове стават съвсем абстрактни в смисъла на "безтипови", или "безполови" - число (int), пойтър (void) или нещо такова. Получаването на такъв int или void осакатява постановка да не може да провери дали тоя тип е подходящ за викането. Дали са ти хендъл към файл, а ти си искал към uart. Аз твърдя че опитите за такова "абстрахиране" на неща, които нямат физическия резон за себе си (примерно uart и spi да ползва общ, "абстрактен" интерфейс) е в ущърб на качеството на кода. Това, че това "приложение" има шанс да работи с различни хендъли, примерно различните уарт-и, spi, ... означава че имаш едно "библиотечно" ниво - това "приложение" е все още абстрактно и ще стане конкретно само когато някой подаде точно определен хендъл / номер на уарт. Т.е. потребителят, който знае дали е уарт1 или spi3 може да даде тази информация и да пусне процеса да работи, т.е. да конкретизира темплейта. И след като е темплейт/абстрактно/библиотечно значи трябва да можем, или по-точно, е нужно, да добавим конкретна информация преди да го пуснем. За да работи по този начин ( с хендълите) ще трябва да съм зависим от още един интерфейс - някакъв "системен" такъв, например "sys.h", "os.h" или нещо такова. Една проста crc функция, която някой е решил да престави по тоя начин, става платформено-обвързана. Или протоколна функция от типа на "modbus_reg_read" става зависима от тоя sys.h или някакъв "transport.h" - защото в тоя стил се предполага че тая функция има още един аргумент, наречен примерно "HANDLE hChannel", който някой е получил след openXXX, примерно openUART(), или open("uart::/0"), или подобен вариант. И функцията modbus_read_reg(hChannel, int reg...) ще включва в себе си викане на channelRead(hChannel) и т.н. Това, което е лошо в горния стил е че в modbus_read_reg() е пред-интегриран точно определен прототип на функция. Т.е. някъде в нейния код се среща реда "channelRead(hChannel, uint8_t* pbyBuf, size_t bufSize)". За да работи това трябва да съм include-нал някъде нейния интерфейс и в кода да има такъв символ (функция, функционален пойнтър). Ако поискам да работя с друг HAL да го кажем ще потърся неговата функция за четене - която се казва примерно "GetData(uint32_t size, int ChannelHandle, void* buf)". Сега, за да я ползвам тая функция в "ОС подхода" трябва да я опаковам да изглежда като channelRead(). В "другия подход" интегрирането на компонентите за да иградят графовете на процесите се случва независимо от компонентите. Т.е. "glue logic"-ата е изнесена извън компонентите и се слага между тях (вместо да се вгражда един нейн твърд вариант вътре в самите компоненти). Компонентите остават непроменяеми независимо дали се е появила друга идея за четене и някой е решил да подобри интерфейса на channelRead(), примерно променяйки типа на size-а, или нещо подобно. При поява на специфичен, не-уеднаквен, т.е. не-доведен до ОС-специфичния интерфейс, компонент - примерно HAL от новия вендор на чипове, който решаваме да ползваме, не се налага да "обгръщаме" фирмения драйвер (функции) с нов wrapper, за да го доведем до познатия ни интерфейс. И това е така, защото новия чип може да има или няма неща, които другите са ги имали. Цялата работа е до това как се справяме с зависимостите - единия подход казва абстрахираме ги, другия казвам борим ги на интеграционно ниво. Не знам дали Zdrav има това предвид, но това което си мисля че показва е че абстракцията може да има смисъл само ако зад нея стои някакъв физически, реален модел на нещо си. Това го споменах в началото - HAL-а може да се опитва да прави абстракция на периферията за CAN само ако представения абстрактен интерфейс отговаря на физическия обект "CAN контролер", който си е описан в един определен PDF и няма мърдане. Другото за фифо-тата или другите примитиви - както говорих в един проект може да имам много процеси, както казваш, и да искам да защитя драйверката функция channelRead() срещу reentrant достъп от различни процеси. Това не бива да води до автоматично слагане на фифо за всеки следващ проект, в който може да има само един клиент на драйвера. Дали ще сложа фифото или не зависи не от това какъв е абстрактния модел на ОС-а, а от това дали имам нужда от фифо или не. В rust езика много наблягат на това, че имат zero cost абстракции -р т.е. нищо от "абстрактните" слоеве не влиза в бинарито за микроконтролера. Тези описания са само за компилатора за да може да изгради правилния код и после ги няма в runtime кода. Аз съм си изградил набор от правила, които следвам или проверявам, за да преценя дали някой подход е "прав" или "крив". Едно от тези правила е дали някъде се губи информация за типа, т.е. дали някъде се налага от конретен тип пойнтър да каст-вам към войд или по-общ, или от структура към някакъв вид число (хендъл). Това ми е първата лампичка, която ми светва за да се върна на "чертожната дъска" и да не шляпам следващото ниво абстракция. Иначе губя почти единствения сериозен помощник, който ме пази да не правя глупости - а именно компилатора. Истинските езици, които обаче за нас са малко недостъпни (за ембедед) залагат на мощна система за типове, т.е. такава в която почти всичко ти е тип "auto" и само входовете ти са конкретни типове (на база на които работят тия auto-та навътре). Никакви каст-ове, никакви войд-ове. Друга лампичка ми е менажирането на паметта и по-точно дали ми се налага да копирам данни само за да ги преставя на някого по очаквания от него вид. Например ако влиза етернет пакет и той е да кажем изтеглен от фифо-то на периферията веднъж в паметта, е недопустимо да откопирам примерно tcp частта от тоя пакет в нова променлива - трябва да използвам пойнтър леко навътре в самия пакет на оригиналната локация, на следващото ниво трябва да излезе пойнтър към още по-навътре в тоя пакет за да се "захрани" следващото ниво. В обратната посока е същото, ама наобратно - в смисъл приложните данни "Hello" се движат като поинтър, tcp слоя трябва да закачи втори поинтър който сочи неговите данни (хедър), после етернета трябва да закачи още един пойнтър с неговия хедър и т.н. Накрая драйвера за етернет контролера обхожда списък от три пойнтъра и си събира пакета, пъхайки във tx фифото от оригиналните локации. Така "hello" може да е дори в ROM зона. За по-смислено описание на такъв вид композиране на отделните етапи (функции) в процеса (приложението) най-добрата референция е pipe-ването в unix shell-а. Имаш отделни функции (инструменти), които знаят само за "вход" и "изход" като данни. Ако искат uart да отиде във файл не променяш cat функцията, а я насочваш към файл. Ако искаш същите данни да се парсират от grep не сменяш нищо друго освен връзката (в смисъл не променяш нито кода на cat, нито на grep). Абстрактното тук са stdin и stdout (и stderr) - това е близко до идеята на RX библиотеките. Т.е. това са прости начини за прехвърляне на данни (буфери) и събития че има нещо. В програмните езици това са аргументите и върнатите стойности. В смисъла на програмни езици това е нещо извън компонентите, което може да вземе данните от един и да ги даде на друг, и това нещо също се пише като програма - т.е. описва процеса на взаимодействия между инстанциите на компонентите. То създава инстанциите и ако трябва добавя glue logic, само че тия лепила са преизползваеми също, т.е. са нови видове компоненти.
|
| Пон Фев 10, 2020 5:52 pm |
|
 |
|
miro_atc
Ранг: Форумен бог
Регистриран на: Нед Фев 26, 2006 6:52 pm Мнения: 11266 Местоположение: Добрич
|
 Re: Въпрос относно собствена библиотека за pic32mx
Параметърчето носи информация на драйвера или на ОС-а. Приложението може да му пука, може и да не пука за тази информация изобщо. Типичен пример е всяко конзолно приложение. То работи с stdin и stdout и може тотално да се абстрахира какво и кой стои зад тях. Да подходът е принципно различен. В единия случай имаш възможност рън тайм да променяш неща, докато в твоя случай нещата са предрешени compile time. Има разлика между това да може да провериш и да не искаш да проверяваш. В ОС подхода имаш избор. В твоя нямаш. Всеки може да си твърди каквото си иска  Аз лично никога не съм се чувствал ощетен, а що се отнася до качеството на кода - мога да ти кажа, че имам наблюдения над доста RTOS-чета и доста библиотечки, писани от най-различни хора и с най-различни подходи. Наблюденията ми са, те този който омазва концепциите се омазва и с кода  Няма "още" един интерфейс. Това е *основният* интерфейс. Мисли логично. Имаш периферия. С тая периферия или обменяш някаква смислена информация или само си губиш времето. Няма трети вариант. Да, понякога е неизбежно да има и housekeeping като примерно да конфигурираш периферията, за да може тя после да ти снася информация. Но основната цел винаги си остава информацията, а не конфигурирания, баяния, челни стойки и т.н. А за обмен на информация нямаш нужда от много специален интерфейс. Просто хендълче с възможност за приемане/изпращане демек четене/писане са достатъчни. Що се отнася до CAN, там нямам опит, но мога да дам доста по-екстремен пример - USB. Toва е малоумщина отвсякъде. Измислени абстракции като ендпоинти, дескриптори, класове и прочие. Като всяко нещо е супер специфично, точно както го искаш - примерно заявките към един вид клас са тотално неразпознаваеми още на протоколно ниво за другите класове. Абсурд някакъв, който не мога да схвана. Затова пък гордо постигат неща от сорта на еднопосочните кабели... Много пъти съм сравнявал с 1394, където единството специфично нещо е... познай! Имаш четене и писане. Хайде имаш и swap и синхронни стриймове, ама това са подробности. Това е. Няма друго. Всичко останало са стандарти, приети много преди и нямащи нищо общо с 1394. Примерно стандарта за configuration ROM. Същият стандарт, който се ползва и при PCI шината. Демек можеш с код писан за сканиране на PCI да сканираш и 1394 устройство. Като и то теб да сканира, защото 1394 използва двупосочен кабел, вместо еднопосочен... Та както в една PCI шина може да имаш няколко и различни карта, така и в 1394 устройството ти може да има безброй функции. Като те може да имат или да нямат нищо общо по между си. Няма нужда от измишльотини от сорта на "композитен клас". Та така имаме една шина която има само четене и писане и друга която има безброй специфични гъзарии. И мога да ти кажа, че едната предоставя многократно повече възможности без почти никакви проблеми... Но уви другата е придобила масовост по разни други причини. Както и да е, въпросът беше че усложненията в някои интерфейси водят само до главоболия и нищо полезно. Но така или иначе са факт и трябва да живеем с тоя факт. В случая с ОС-а това означава, че обикновено се прави "стек" над специфичния интерфейс, за да може той да се преобразува до някакъв по-човешки такъв. Примерно в случая с USB, стекът като види че отсреща има CDC създава "виртуален ком", който приложението чете-пише както би правило с всяка друго входно-изходно устройство. Приложението няма работа със специфичните за USB изгъзици, те не го вълнуват, вълнова го ком-порта и по точно информацията, която може да се прати или получи. Пак ще повторя смисъла на всяка една периферия - да обменяш полезна информация. Да, винаги ще се намери идиот, който да проектира периферия, която да изисква челни стойки и от това нас да ни боли глава. И когато се сблъскам с такова нещо - пиша драйвер или стек или библиотека, която максимално да изчисти кашата, която са забъркали. И от там нататък да мога да ползвам тая периферия по един по-нормален начин. С други думи когато видя едно лайно гледам да го опаковам и да смърди по-малко, не се опитвам да го размазвам, да го копирам или да го украсявам....
|
| Пон Фев 10, 2020 8:42 pm |
|
 |
|
gicho
Ранг: Форумен бог
Регистриран на: Пон Мар 13, 2006 1:59 pm Мнения: 3867 Местоположение: Габрово
|
 Re: Въпрос относно собствена библиотека за pic32mx
Не, тук е разковничето - в хардуера има такова нещо като ендпоинт - всеки опит да го скриеш ("абстрахираш") е стъпка в грешната посока. Емулирането на com порт какво общо има? Имаш десетки други варианти, как така cdc-то е универсалния? Какво прави един необременен с историята на техниката програмист като му кажеш да конфигурира бод рейт или фрейминг формат през усб? Ще ти кажа - я разбрал, я не разбрал пише "115200", "8n1". Трябва да прекарва нещо през етернет и там пак се появява функция за конфигуриране и задаване на бод рейт и фрейминг  Или обратното - в приложението виждаш как някой вика някакви функции да сетва 10 или 100мбит, full или half дуплекс, а то работи през ... i2c накрая. Емулиране на com over usb си е конкретна задача и тя няма общо с емулирането на com over spi примерно (освен интерфейса, през който се достъпва емулираното нещо, макар че той трябва да има отделна част за конфигуриране на емулацията - имена/усб дескриптори, ...). През usb изрично трябва да изискваш достъп до ендпойнтовете за да се възползваш от неоценените екстри да имаш няколко "канала" през един порт (контролен ендпоинт, данни в двете посоки в друг). И ако някой ти е сложил една "абстракция" да имаш "/dev/usb1" примерно, при което write() върху него няма как да се възползва от 16-те ендпоинта, щото няма да работи с .. уарт или спи, или друга имплементация на абстрактен дивайс, а само ползва единия ендпоинт (виртуален канал - щото на уарт има само един и не може другите имплементации да имат повече), та тогава ще ти се наложи да направиш протокол, с който да дефинираш различни типове пакети и да прекараш този протокол през единствения ендпоинт, с който можеш да работиш. Конкуренцията няма тия "екстри" и задвижва 16-те ендпойнта на максимум - твоя код може би е останал непроменен спрямо реализацията върху уарт, но устройството работи пак толкова бавно, колкото преди ъпгрейда до усб. Така де, само че няма как да не му пука, защото ако не му пука ще каже "я, хендъл, я не ми пука, я няма да го дам нататък...". Т.е. трябва да му пука и трябва да спази изискването да го подава на всяко викане на функция. Не ползва стойността, не я модифицира - само я прехвърля нататък. И въпросът е има ли начин да не се товари с това прехвърляне, и да не се обвързва с зависимост от тоя тип. Именно - кой конзолен инструмент е "заточен" за работа само с определен хардуер, или има нещо общо с абстракцията, или му пука за нещо друго освен суровите данни? Искаш нещо да се конвертира от бинарно в някакъв json примерно - къде тук тоя инструмент има нужда да знае тоя json на ком, или на сокет ще го хвърляш? Виж, ако инструмента се казва "BinToJsonToSocket" то много вероятно е да има аргументи от реда за тип на сокет, порт, адрес, .... Което може да се реализира като отделен тул, които прави BinToJson и отделен socat/nc или подобен. По-скоро в OS подхода нямаш шанс да провериш преди да извършиш самото викане рънтайм - типът "typedef HANDLE void*" е дефиниран и не ми помага да знам дали е ок да ползвам дадена стойност или не. Като ми дойде един windows хендъл примерно няма как да знам дали е коректно да повикам write() с него като аргумент, щото нямам информация - HANDLE като тип е валиден. Това, което искам е кода да гръмне по време на компилиране ако билдвам за таргет, който примерно няма uart, а аз съм решил да отварят uart0. Още по-добре ще е да гръмне ако викам open() с бод рейт "EN_UART_SPEED_115200", а дадената платформа/таргет поддържа до 57600 и в енум-а typedef enum {} EN_UART_SPEEDS липсва ентри за 115200. В chibios има нещо подобно - прерифериите са глобални символи, например SD1 мисля беше за уарт1. Ако ползваш SD5, а дадения борд/процесор няма такъв, то кода не се билдва - супер логично и естествено поведение ми се струва. Откъде примерно в по-ОС подхода знаеш кои скорости са налични на дадения хардуер? Общо взето не можеш да знаеш и затова или пускаш през абстракцията всички известни и рънтайм гърмиш с грешка ако не се поддържа, или пускаш най-орязания сет от скорости, които се поддържа от всички имплементации. Само че и в двата случая има шанса следващата платформа да добави нещо ново, или да не поддържа нещо от "задължителния" списък. В другия подход се изисква тази информация да е налична и пълна към момента на билдване, което е валидно само за таргета, за който тая информация е вярна. Т.е. появата на нов модел платка с поддръжка на повече портове или други скорости дава ново описание, но и изисква да се билдне кода отново за да се вземе в предвид новата таргет информация. Това не е проблем и става съвсем лесно автоматизирано, така че не е нужно някой да го върши ръчно дори. Ако излезе проблем (билда гръмне) някой може да го нагледа защо не минава. Оттук идва и още един бонус, който има връзка с другата тема за платформа за управление на софтуерни проекти и CI - билдването се прави при промяна на някоя от зависимостите. В конкретния случай бинарито за модел А1 е зависимо от сорс на проект А, тулчейн X и хардуерно описание на модел 1. Промяната в някой от тия трите неща води до нов билд (ново бинари), и после евентуално до тестове, пускане на нова версия и т.н. Модел А2 обаче е зависим от сорс А, тулчейн Х и хардуерно описание модел 2. Смяната в хардуерното описание на модел 2 не влияе върху бинарито на модел А1, но води до билдване на бинари А2. Дори в общия сорс А да е имало драйвер за уарт, ако хардуерното описание на модел 1 няма уарт, а модел 2 има, то промените в сорса на uart.c няма да доведат до ново бинари за модел 1 (и няма ново тестване, няма ново сертифициране, документации ...). А всъщност бинарито за модел 2 си има уарт и той си работи. Това ще се получи ако софтуера (сорс А) е организиран така че сорса от uart.c изобщо да не се компилира и линк-не в бинарито на А1. Има една неосъзнатата разлика между ембедед и ПЦ, или по-точно различните нива на надеждност - в ПЦ-то това че ще вдигне грешка не е критично, в ембедед е по-важно да няма ексепшън, дори ако user-а бъде разочарован с грешка при компилирането и трябва да прецизира описанието. Щото при ПЦ пускането на програмата става от user пред терминала и ако има грешка ще я види и ще направи нещо. В ембедед това ще е нейде надълбоко в шкафовете на машината в цеха на майната си и оправянето ще коства много повече. Всъщност в някой области с по-високи нива на сигурност подобен код няма да стигне до рънтайм гърмене - такива конструкции няма да позволят да вземе сертификат че да стигне до инсталиране и пускане. Ако имаш device tree на някаква таргет система, или друго подобно описание, ще позволиш ли съзнателно да се зарежда програма на тоя таргет, за която знаеш че ползва неналични ресурси (интерфейси)? И ако позволиш, а конкуренцията предупреди или даже визуално покаже само листа от наличните портове, понеже програмистът е написал "джаджаМодел1Конф3", кой ще вземе бонуса? Пак като разлика между ембедед и ПЦ - при ПЦ нямаш достъп до сорса на приложенията, които потребителят инсталира. Ти даваш ОС и хардуер, той си пише нещо ново, билдва го без твое знание, и го качва и пуска. Трябва да се закачиш някак в билд процеса му за да можеш да му светнеш грешка при билд "Дивак, SPI43 ще викаш на ....". При ембедед е нормално приложенията да се проверяват преди да се сложат и пуснат в употреба - дали компилиране, дали тестове, сертифициране, приемо-предавателни и т.н. Т.е. имаш точки, в които можеш да провериш по един или друг начин много повече аспекти в приложението и да изревеш много по-рано за проблеми. Това е и очаквания процес на работа и не бива да се меша с другия (десктоп/пц). Следователно компромиси, които са приемливи в едното не биват да се пренасят по инерция върху другото. Съгласен съм че прилагането на такъв подход много често вдървява приложението - няма да стане да имаш едно бинари, което да можеш да флашнеш на всички модели джаджи. Само че за мен това вдървяване е необходимо заради стъпката на deploy-ване и пращане в тамбукту, където много вероятно и да няма интернет за да смениш фирмуера при нужда. Отделно добавянето на гъвкавост на определени нива (при нужда) не е трудно и винаги може да се добави фифо вместо директна връзка, или мултиплексор с възможност за runtime смяна. Това обаче не изисква всяка връзка между два компонента да има по дифоулт и фифо, и мултиплексор, и звънче. Когато някъде имаш нужда да избереш "принтер" или "gps" или "modem" на uart0 ще ти се наложи да сложиш "мултиплексор" в кода. И тъй като е много логично променливата който избира канала на мултиплексора да управлява и разрешенията на разните софтуерни модули, то не ти трябва защита от няколко клиента.
|
| Вто Фев 11, 2020 12:39 am |
|
 |
|
miro_atc
Ранг: Форумен бог
Регистриран на: Нед Фев 26, 2006 6:52 pm Мнения: 11266 Местоположение: Добрич
|
 Re: Въпрос относно собствена библиотека за pic32mx
Ти май не вдяваш за какво ти говоря... Ендпойнта е абстракция на USB интерфейса. Глупава и абсолютно ненужна абстракция, която само те ограничава. Да прекарваш през ендпоинт някакъв хардуер често е като да прекараш слон през иглено ухо. Дадох ти пример с друг интерфейс - 1394, който не налага излишни абстракции. Единствената "абстракция" която ти дава е, че всяко устройство в шината за теб изглежда като memory mapped. От тук нататък говориш с всяко едно устройство като че ли все едно ти е вързано на локалната шина. Няма нужда да минаваш през каквито и да е било абстракции. Няма нужда да се чудиш що е то ендпойнт, колко ендпойнта имаш и тем подобни глупости. Искаш две, три или пет устройства да си говорят помежду си - никакъв проблем. Не само че няма абстракции, ами даже няма нужда от CPU да им посредничи. Примерно така се прави стриймване на няколко камери директно във видео паметта на графичната карта. Софтуерът е необходим само за да включиш камерите, да избереш режимите и форматите, коя камера къде да се показва и до там. Пускаш и процесора може да ходи да спи. Няма нужда от него, защото няма ендпоинти, няма нужда от претакване пакет по пакет, кое от къде е и защо. На практика всеки един хардуер изглежда като памет или набор от регистри. Така че 1394 е просто една прозрачна среда през която виждаш директно хардуера. Самата среда не я интересува какво виждаш ти, или какъв е хардуера. Правя сравнението между USB и 1394, защото и двете са интерфейси към някакъв хардуер. Едното е прозрачен интерфейс, другото е нещо като криво огледало. Дано да си схванал разликата... Същото е със софтуерните интерфейси. Те може да са прозрачни и универсални, а може и да не са. Драйверен интерфейс базиран на четене и писане е универсален и това само ти дава възможност да боравиш с каквото искаш и както искаш. С нищо не те ограничава. Ако искаш може да проверяваш и ЕГН на тъщата на дизайнера на съответния хардуер. Ако искаш може и да не го проверяваш. Твоя воля. Но прозрачността и универсалността са задължителни неща, ако искаш да имаш преизползваемост. Без тях няма как примерно да седнеш и да напишеш код за периферия за която още няма хардуер, няма и драйвер. А това е ежедневие и се налага както в бъдеще, така и минало време. Демек може да имаш код, който си писал преди 10-15 или 20 години (аз имам много такъв код) и ако той е работил на един хардуер, днес да си работи на коренно различен. Естествено, че драйверите дето съм писал за gprs няма да работят с wifi хардуер. Но приложенията ми за gprs си работят като пушка и през wifi и през ethernet и утре ако пуснат 5G вероятно и през 5G ще работят (надявам се). Защо? Защото не чета заданията буквално, ако едно време клиента е казал искам "gprs" той не ми е казал "ожени се за gprs". Той е избрал gprs като най-актуално към момента, но реалната му нужда е информацията да стигне от точка А до точка Б. Бих се оженил за gprs само ако правя gprs модеми, но аз не правя модеми... правя устройства, който работят с информация. Как точно мачкат информацията и как точно я обменят това са подробности и тези подробности се менят с времето. Устройствата ми ще се продават докато има нужда от съответната информация. Ако не дават тая информация, ако ще и 5G и 6G да им сложа е все тая и няма да се продават. И пак ще каже, че когато имаш възможност не означава, че трябва да се възползваш. Не е някаква тайна, че често се произвеждат устройства със заключени функции. Шефовете казват това ще го отключим ако клиента си плати. По същия начин, това че имаш възможност да работиш с дадена периферия по стандартен начин, не означава че нямаш възможност да ползваш нестандартните й функции. Ти си избираш просто. Естествено си знаеш, че като ползваш нещо специфично утре като смениш желязото може да има изненади. Но тези неща не касаят драйверната система и не бива да я касаят. Както и да е, дадох ти възможност да ме разбереш... който разбрал - разбрал, аз бях до тук! 
|
| Вто Фев 11, 2020 10:37 am |
|
 |
|
gicho
Ранг: Форумен бог
Регистриран на: Пон Мар 13, 2006 1:59 pm Мнения: 3867 Местоположение: Габрово
|
 Re: Въпрос относно собствена библиотека за pic32mx
Съгласен съм че да спорим така не е от полза за никого. Обхождаме много теми и сменяме примерите та съвсем се загубихме. Дискусия може да има ако измислим някакъв use case и се опитаме да разгледаме няколко имплементации в различни подходи. Тогава можем да оценяваме кое е по-добро според някакъв критерий - лесно за писане на приложения, лесно за портиране на друг хардуер, преизползване на максимален процент от кода, защита от грешки, рънтайм ефективност, ... Интересно ще ми е да видя код от някой познат на теб ОС, в който тази абстракция на дивайс от високо ниво работи ефективно и позволява приложението да се възползва от екстрите на реалния интерфейс отдолу (вместо да ограничава API-то до общото подмножество от read() и write() само). Има всъщност един подход, който решава тия проблеми, ползвайки съвсем просто и стабилно API - това е REST принципа, при който имаш "ресурси" като идентификатори и няколко метода, които са валидни винаги за всички "ресурси". Тия ресурси за URI-та да кажем най-общо, а методите са GET/POST или PUBLISH/SUBSCRIBE. За да работи това се изисква идентификаторите на ресурсите да следват точно модела на нещото което представят. За SPI примерно нещо такова като йерархия: При такава организация пращането може да става чрез publish("spi/0/data",0x1234), а CS може да се контролира чрез publish("spi/0/CS", 0). Получаването на данните става чрез абониране за data пропъртито примерно subscribe("spi/0/data", OnDataReceivedCallback). В този случай различните характеристики на нещото (SPI) са достъпни и "обектите" имат фиксирани методи (publish, subscribe). Това всъщност е реализирано в MQTT-то и много други. Послеслов (ако на някого му се чете): Какво общо има мемори мапед перифериите и усб - в единия случай при firewire някой в хардуера се грижи за това да престави всички външни устройства като региони в паметта - което става с много обмени отдолу, които са имплементирани сигурно в хардуера/фирмуера/ром/драйвер на хоста и дивайсите. Това къде засяга темата за софтуера - ако нещо работи самостоятелно и примерно закарва картината от камерата до монитора, без да изисква софтуерно конфигуриране, за кой софтуер говорим? Абстракцията с виртуална I/O зона (това memory mapped) е удобна в определени случаи, и противопоказна в друга - даже само от това следва че не искаш да представяш всеки възможен дивайс като мемори мапнат, или пък като char, или като SPI-специфично АПИ. При мен водещия стил на API гледам да е евент базирано, при които нещата от долния слой (по-близкия до хардуера, примерно uart_stm32.c драйвера) скрива всичката специфика и от него излиза "OnDataReceived()" колбек/event, т.е. няма read(fd) - това е приключило към момента в който е закачен колбека. А закачането на колбека е в друг интерфейс, който може да е общ с този за конфигуриране. Ако OnDataReceived() има само pbyData и size (и може би контекст на клиента pvMe) той е онази абстракция за прехвърляне на данни. Т.е. ако имам нужда да работя с различни периферии (уарт/спи/и2ц) е достатъчно всяка от тях да предостави механизъм за регистрация и викане нa OnDataReceived(). Тук онова pvMe почва обаче да има лошия характер на fd хендъла (щото е от недефиниран тип и скрито зад void* или число). Имам предвид че тази функция OnDataReceived() е близка или дори еднаква между разните периферии - макар че и тук е условно заради войда и size-а, които по всяка вероятност в хедъра е описан като uint32_t или size_t и скрива това, че CAN ще докарва максимум 8 байта данни и т.н. Обаче по време на обмен на данните се случват и други събития, освен приемане на данни - например break събитие на уарт, линк up/down на етернет, на CAN има warning и error, има потвърждение за изпратен пакет. През абстракцията hDev.read() и hDev.write() това не може да премине. Затова има шантавото IO control с много кодове, голяма част съвсем специфични за една периферия и тотално ненужни за друга. Само че в момента в който приложението повика deviceiocontrol(XXX) то е навеки свързано да работи само с периферии, които имат ХХХ командата. И кода не е преизползваем - в този случай се появява повикване на XXX, проверка за грешка, викане на YYY, ако сбърка викаме ZZZ, ако и то сбърка превключваме логиката на приложението да почне да ползва ААА, БББ, ЦЦЦ. Това не е добре и е индикация че някой е "измислил" абстракция, вместо да се чукне по главата и да каже - ей тия двете функции имат тотално еднакъв прототип, значи мога да си позволя да ги обединя. В силните като type система езици онова size ще се знае че е макс 8 ако се достъпва CAN и няма да сработи, ако някъде някой поиска да вкара стойност, по-голяма от това. Или онова с бодрейта, за което писах преди - само че да обърнем size аргумента на enum и така да си гарантираме че няма как да ни подадат повече от 8 не е удобно решение, но все пак е някаква теоретична възможност. Не познавам в детайли OHCI/EHCI и наследниците, но доколкото знам там много хардуерни "ускорения", които да махнат нуждата от това софтуера да обръща внимание на всеки дивайс на всяка милисекунда или на 125мкс. Което пак ни води до това че трябва да има някой (драйвер/ХАЛ), който да познава спецификата на OHCI реализацията на интел (примерно), но от другата страна да излезе като преизползваем интерфейс. Това, което твърдя аз, е че има едно ниво, което се намира в примерно intel_ohci.c и експортира интерфейс, които се казва ohci.h - и не експортва интерфейс наречен "dev.h" или "sys.h" или "transport.h" с по вдна read и write функция.
|
| Вто Фев 11, 2020 4:04 pm |
|
 |
|
miro_atc
Ранг: Форумен бог
Регистриран на: Нед Фев 26, 2006 6:52 pm Мнения: 11266 Местоположение: Добрич
|
 Re: Въпрос относно собствена библиотека за pic32mx
Нещо не ми се бачкаше, затова си позволих малко писателстване на тема как трябва да изглежда интерфейса между софтуер и хардуер… Забележка: това не е отговор на някой пост, въпреки че ще повторя някои опорни точни. Но с цел систематизация, а не продължение на предишна дискусия.
И така… темата е интерфейс между софтуер и хардуер. Под хардуер обикновено имаме предвид различни периферии. А под софтуер различни задачи, които трябва да се свършат със или без периферии. Важното в случая е връзката помежду им. Обикновено това е връзка от типа “много към много”. Може да е една към много или много към една, но ситуация “едно към едно” е практически безинтересна и можем да я изключим. Нуждата от дефиниране на интерфейси е най-вече заради връзки, при които поне в едната страна имаме повече от една маймуна. По същата логика тъй като имаме няколко софтуерни задачи или няколко периферии, то следователно имаме система с някаква форма на многозадачност. За краткост наричаме това ОС, дори когато “нещото” е писано в гаража и автора му няма претенции за нищо. Просто трябва да има многозадачност и каквато и да е тя, я наричаме “OС”. И за да завърша с термините – покрай всяка периферия обикновено има някакъв специализиран код. Този код може да е всякакъв, но за краткост го наричаме “драйвер”. О, да.. ще повторя и дефиницията на периферия – това е животно, с което искаме да си обменяме някаква смислена информация. И така… темата с новите термини става “интерфейс към драйвери в един ОС” в най-широкия смисъл на тези понятия. Формата на интерфейсите варира според конкретния ОС, драйвер и т.н. Най-често е оформен като С-функции и някакво API, но може да са някакви съобщения, заявки и т.н. Няма да задълбавам в тая посока, а ще се опитам да систематизирам тези функции, заявки или каквато комбинация се ползва, според два аспекта. Първият аспект е синхронизацията между клиента (софтуерна задача или драйвер) и конкретния дравер. В това отношение имаме синхронни и асинхронни функции на драйвера. Синхронните са ясни, там клиентът иска нещо, драйверът го прави. Практически е като викане на функция. Влиза, изпълнява се, излиза. За да няма инфекции, обикновено или драйверната функция се спасява чрез критични секции, семафори и т.н. Или пък се сменя контекста при извикването и излизането. Вторият вариант по принцип е по-удобен, защото се избягва честата употреба на различни синхронизационни примитиви. Така нито клиентите нито драйверите имат нужда от семафори. Освен това смяната на контекстите е свързана и със смяна на стекове, така отпада нуждата примерно ако някой пипне даден драйвер и увеличи stack usage-а няма нужда да се обхождат всички клиенти и да се пипат стековете им. И от гледна точка на секюрити, юзер мод и т.н. най-добре всяка жаба да си знае гьола. Естествено синхронните функции са удобни само за неща, които драйвера/периферията могат да изпълнят веднага. Но както вече уточнихме, говорим за някаква многозадачност и типично перифериите имат нужда от някакво време. За такива неща се ползват асинхронни функции. Тези функции са по-скоро “заявки”, при които клиента казва “искам еди какво си”, което често на практика се записва точно като заявка или в хендълче. Това нещо (каквото и да то) отива до драйвера, драверът почва да го обработва. Ако може да го обработи веднага – добре, ако не се изчаква. Примерно, ако заявката е да се приемат данни то очевидно трябва да се изчака те да дойдат, ако не са дошли. Когато дойдат, или ако не дойдат в указания срок, заявката се приключва и поема обратния път към клиента. По принцип ОС-вете предлагат различни варианти за асинхронните функции: - блокиращо викане, ако клиента няма какво друго да прави просто вика тоя вариант и той излиза, когато заявката приключи. - блокиране + таймоут – същото, само че да не се отвее вовеки, има таймоут. – неблокиращо викане – заявката просто се подава, ако може се обработва, но при всички случаи управлението се връща и клиента може да си върши някаква друга работа и след време да проверява за резултата. Тези варианти обикновено касаят само викащата страна. Към драйвера при всички случаи отива заявка, която той обработва когато и както може, без да се интересува дали клиента спи или не спи. Вторият аспект по който условно се делят функциите на драйвера са на стандартни и нестандартни. Както казахме по дефиниция всяка периферия обменя информация. Но понякога една и съща информация може да бъде обменяна през различни по тип периферии. Това важи за всички комуникации, а и не само за тях. Очевидно е добре програмистите да знаят коя функционалост е стандартна, т.е. може да ползват без да се притесняват, че ако утре драйвера се смени ще трябва да променят кода си. Съответно и степента на стандартизиране. Примерно мрежовите интерфейси от рода на gprs, wifi, ethernet и т.н. обикновено имплементират сокети. Очевидно сокетът е стандартен по всеки един смисъл на думата. Но всеки един интерфейс може да имплементира и нестандартни функции, които няма как да са стандартни. Примерно gprs-a може да връща името или кода на оператора, дали е роуминг или не, може да връща IMSI, ICCID и т.н. Неща, които нямат аналог при другите интерфейси. Но пък да кажем те може да са стандарт на ниво gprs драйвери. Освен да познават кое е стандартно и кое не, въпрос на добра практика е програмистите да разделят кода от гледна точка на кое може, кое не може, кое трябва и кое не трябва да се портва. Това специално го подчертавам за @gicho, който толкова много се притеснява че видите ли не можел да провери конкретиката. Винаги може, въпросът е че правилното място за тия проверки е в портируемата част, а не в библиотечната част. Статистически библиотеките вдигат надеждността поради простата причина, че се ползват в много проекти/места. Но те са библиотеки, само защото правят общи неща. Ако ги насереш с проверки за конкретика, вече няма нищо библиотечно в тях. По същата логика, ако драйверите не следват стандарти в интерфейсите писането на библиотечен код става мисия невъзможна. Тук някой ще каже “wrappers”… да, понякога минава номера. Само че те ако нещата не са проектиране още на ниво драйвери да са универсални, може и враперите да не помогнат. Особено когато трябва да се синхронизират няколко неща, ама единия ползвал критична секция, другия семафор, трети полиране. Върви пиши врапери за такива бози. Най-малкоя проблем в случая е овърхеда. Освен че драйверите могат да предлагат стандартна функционалност, те могат да я предлагат и по стандартен начин. Всъщност дори и нестандартните функции е редно да са по стандартна имплементация, защото примерно може да има един таск, който иска да работи асинхронно с няколко драйвера. И така обобщение и пример… Естествено, най-лесно ми е да дам за пример нещото което ползвам. Освен автореклама (или антиреклама), то е правено след... как да кажа… леко взаимстване на най-добрите идеи оттук-оттам. Драйверите се имплементират като 3 функции. Едната е ISR и мисля, че е ясно какво прави. Втората е за синхронни заявки или добре познатите io-controls. И третата функция е за асинхронни заявки, демек има хендъл. Разделянето на синхронни и асинхронни мисля, че е ясно защо. Очевидно има разлика в параметрите на функциите. И очевидно, че ако няма нужда от хендъл за дадена операция по просто е да си го спестим и от страна на клиента и от страна на драйвера. От друга стана, ако операцията не може да се изпълни веднага, то е ясно че е асинхронна и за целта си трябва хендъл. Що се отнася до стандартни/нестартни и двете функции го позволяват. Има стандартни io-контроли като ресет, има и нестандартни според вкуса на драйвера. Четенето/писането по дефиниция са си стандартни операции и няма драйвер който да не поддържа поне едното. Демек всеки драйвер, които може да снася информация поддържа read с хендъл. Всеки, който може да пише поддържа write. И винаги поне едното се поддържа и винаги е стандартно. С хендъли може да се правят и нестандартни операции, т.е. нещо като io-контроли през хендъл. Аз ги наричам команди, но това е въпрос на терминология само. Това май изчерпва всичко за драйверите… Хендълите Мисля че съм обяснявал вече, но пак ще кажа това е една структура в която има всичко за заявките, а именно: - указател към клиента - указател към драйвера - операция (четене, писане, транзакция и команда – побитово кодирани, т.е може да е комбинация) - указател към сорс за данни (валиден при write) - указател към destination (валиден при read) - дължина за данните (ъпдейтва се накрая) - състояние/резултат на заявката - имам и prev/next, които са само за удобство на драйверите, в случай че искат да си правят опашки от заявки, а те обикновено искат  Функции за клиенти Клиентът естествено не вика директно функции на драйвери, вика си системни функции. Съответно има функции за: - io-controls - четене/писане, четене и писане едновременно, с таймоут, с блокиране, без блокиране, изобщо всичките им комбинации. Всичките се свеждат до попълване на полетата на хендъла и евентуално различен ефект върху клиента, т.е. дали ще блокира и т.н. - команди с хендъли - open & close. Това по принцип са io-контроли, при които се иска разрешението на драйвера, понеже той може да откаже отваряне на хендъла примерно. Или да следи броя на клиентите и т.н. Сокети и файлове Както много пъти повторих всички драйвери поддържат четене/писане и тия операции винаги са стандартни. Но при някои драйвери преди да се стигне до четенето или писането има нужда от лека подготовка. За целта има сокети или файлове, които просто са наследници на хендъл, но с добавена функционалност. Добавената функционалост е ясна, имплементацията естествено са командички от сорта на bind/connect/file_open/close/delete и т.н. Просто тия командички са си стандартните за съответния клас и съответно са стандартни команди за съответните драйвери. Така че за някои драйвери не става просто да отвориш хендъл и да четеш/пишеш. Трябва сокет/file и да извикаш съответните заклинания. След това тъй като сокета или файла са наследници на хендъла, спокойно може да се подаде на библиотечен код, който да си чете или пише без да се интересува дали го прави във файл, дали сокет или някакъв обикновен друг драйвер. Mode или режими. Отварянето на хендъл, сокет или файл изисква едно параметърче mode. Този режим си е стриктно според драйвера. Естествено за сокет и файл са си относително стандартни, но за останалите драйвери е каквото те искат. Обикновено това са няколко поленца със стойности, които трябва да се набият в някои регистри на съответната периферия, че да влезе в съответния режим. Винаги се стремим полетата и регистрите да си съответстват, защо така много по-лесно се проследяват нещата. Освен това е много по-бързо, защото в идеалния случай драйверът просто копира едни стойности. Евентуално плюс някоя -друга проверка за всеки случай, против груби изцепки. Изключения правят неща като baudrate, там се попълва желаната стойност. Примерно 9600, а пък драйверът като му дойде времето си прави сметките в зависимост от системния или неговия клок. Кодът за всичко това го има в гитхъба, линка е в раздела с проектите... Това за моя, иначе както казах има много други под небето 
|
| Вто Фев 11, 2020 9:02 pm |
|
 |
|
Dimitar
Ранг: Форумен бог
Регистриран на: Пет Ное 12, 2004 3:38 pm Мнения: 9103 Местоположение: Chicago, IL
|
 Re: Въпрос относно собствена библиотека за pic32mx
Миро, какъв е точния линк към примера, за който говориш и най-много се доближава до твоята идея как трябва да станат нещата? Същото бих попитал и Гичо, за да можем да сравним как изглеждат сорсовете, че така с тия фермани е малко сухо за смилане  .
|
| Сря Фев 12, 2020 12:27 am |
|
 |
|
Dimitar
Ранг: Форумен бог
Регистриран на: Пет Ное 12, 2004 3:38 pm Мнения: 9103 Местоположение: Chicago, IL
|
 Re: Въпрос относно собствена библиотека за pic32mx
Миро, няма нужда от линк - намерих го в темата за проектите.
|
| Сря Фев 12, 2020 3:40 am |
|
 |
|
gicho
Ранг: Форумен бог
Регистриран на: Пон Мар 13, 2006 1:59 pm Мнения: 3867 Местоположение: Габрово
|
 Re: Въпрос относно собствена библиотека за pic32mx
Миро, добре си описал нещата и ще си позволя само конкретни коментари с идеята, че аз говоря за реактивна система, а не императивна. С две думи, в софтуера, както и в хардуера, прехвърлянето на данните има още един аспект, който ти наричаш синхронизиране. Един друг поглед върху това "синхронизиране" е да се каже че има нужда от flow control на данните, които се движат - синхронизирането решава как да знаем кога е разрешено да го подадем на драйвер (примерно). А flow control трябва защото тоя процесор там е сложен за да реализира някакъв обработка на данни, т.е. от едната страна влизат едни данни, а от другата (другите) излизат (ако едно от двете не е изпълнено тая "черна кутия" само хаби ток). Данните влизат и излизат САМО през периферия, затова както и да го въртим, стигаме до това данните от уарт (ADC, usb gprs) да влязат, да минат през софтуер (няма значение какъв) и да искат да излязат някъде другаде - DAC, етернет, SPI(-флаш), USB(диск), USB принтер,.... И има простата логика че ако производителят (producer) на данните е по-бърз от консуматора (consumer) имаме нужда от flow control. Точно както на uart ни трябва такъв (хардуерен, софтуерен) ако не искаме да загубим данни. Може да е дори само за да светнем червена лампа "overrun" и да умрем безславно, но трябва да правим нещо. Разбира се софтуерните блокчета също могат да се окажат бавни (примерно искат да сметнат и проверят някаква чексума и са бавни) и затова и те могат да се окажат "забавителя". Същото може да се осмисли по-лесно ако кажем че тоя блок (crc) можеше да е хардуерен на мястото на функцията за crc имаше обръщение към периферия, която трябва да чакаме. Тъй де, както и при хардуера ако накачуля вегига от 10 уарт-към-уарт, за да минат данните трябва да изградя цялата верига от flow control линии - ако между 5-ти и 6-ти сложа три-пинов кабел вместо пълен null modem примерно, то дори всички други да са пълни то flow контрол веригата ще умре. Моята цел е да постигна същото нещо в софтуера - блокове, които могат да правят flow control и да си взаимодействат помежду си - викат му "back pressure" - ако следващия не може да смогне ще вдигне "налягането" на входа за да не може предишния да му вкара нови данни. Това ще вдигне налягането напред по веригата и така до TCP сокета на входа, който ще спре трансфера (в ПЦ-то на другия край на света), или ще вдигне сигнала на серийния към gprs модема, който ни вкарва данните. https://no-kill-switch.ghost.io/whats-backpressure-what-youre-missing-by-not-knowing/https://nodejs.org/en/docs/guides/backpressuring-in-streams/Номерът е как всички интерфейси в тая система да поддържат това "обратно налягане" и flow control. В перифериите тази концепция се прави от прекъсвания за готовност на предаването TX_READY или FIFO_LEVEL, които са началната точка, която "цъква" flow control-а че драйвера/клиента може да пише ако иска (и ако има недовършено писане). Ако няма недовършено (няма чакащи данни то следващото записване ще стане когато след час дойдат данните. Тия прекъсвания могат да се обърнат до тредове, ако има нужда, т.е. ако има много паралелно работещи "вериги", свръзващи входове и изходи. Тогава ще има нужда от приоритети и ако interrupt системата на тоя контролер не стига като нива може да се добавят повече "нива". Такива се налагат когато през тия данни минават протоколи, които имат някакви виртуални канали, които има някакви изисквания за QoS. По моите разбирания това е архитектурата, която трябва да има в софтуера, за да бъде той ефективен. Такава архитектура има разните reactive имплементации - например Rx (RxJava, RxJs) и подобни.
|
| Сря Фев 12, 2020 11:40 am |
|
 |
|
miro_atc
Ранг: Форумен бог
Регистриран на: Нед Фев 26, 2006 6:52 pm Мнения: 11266 Местоположение: Добрич
|
 Re: Въпрос относно собствена библиотека за pic32mx
Абе ние сме несравними би, как така ще ни сравняваш  Извън майтапите, както писах по-горе идеята е, че новобранците е добре да хвърлят по едно око на различни подходи. Не защото има по-по-най, а защото са си различни. Аз съм описал що-годе класическия подход, класически е защото това се преподава все още като основен в дебелите книги. Гичо пък е фен на евънт и message базирани организации и т.н., което също съществува като теория, но малко хора го практикуват и ако искаш да го видиш на практика реализирано ще удариш на камък. Което не значи, че теорията му е грешна, просто малко хора я практикуват. По ирония на съдбата аз в "по-ранните" си години също бях фен на евънтите и съобщенията, а това което сега ползвам, го ползвам щото трябва да си вадя хляба. Но като теория пък ме вълнуват по-различни подходи, но те още са прекалено млади, пък аз вече взех да остарявам и както се казва старо кучи трудно учи нови номера  Синхронизирането като проблем възниква винаги когато имаш повече от една маймуна и само един банан (ресурс). Няма значение каква ти е системата, дали демокрация или комунизъм, проблемът си е проблем. В програмирането има различни техники, вика им се "синхронизационни примитиви" с които може да се реши такъв проблем. От изборът на примитивите после се класифицира системата. Ако за банана искаш пари или дупе, значи си гаден капиталист. Ако го делиш по братски значи си тъп комунист. Но ако забелязваш, аз май никъде не съм споменал какви точно примитиви използвам, може леко да загатвам или се подразбира... Но това не е важно, важното което се опитвах да обясня е, че трябва да внимаваш да не ги смесваш прекалено. От това боли глава. Стандартизирането опростява много нещата. Затова и аз ползвам един определен примитив почти навсякъде и не само за драйверите. Така маймуните по-малко се бъркат и по-добре се разбират помежду си. Би било прекалено сложно, ако на едни маймуни им искам пари, на други не искам... получават се интриги само  Аналогията ти с флоу-контрола също илюстрира проблем със синхронизация, както и начин на решаване. Хубаво е обаче проблемът и решенията да се дефинират поотделно. Най-малкото защото за един и същ проблем има различни решения. Но още по-важно е, че всяко решение решавайки едни създава други проблеми. Така на практика избирайки си инструментите ние избираме не толкова какви проблеми ще решим, а какви ще си създадем. Щеше да бъде идеално да има инструменти, които да решават проблемите "безпроблемно" веднъж и завинаги. Уви, няма пълно щастие.
|
| Сря Фев 12, 2020 12:38 pm |
|
 |
|
Zdrav
Ранг: Форумен бог
Регистриран на: Сря Яну 26, 2005 2:01 pm Мнения: 1952 Местоположение: Варна
|
 Re: Въпрос относно собствена библиотека за pic32mx
Вече трети ден се опитвам да намеря време да се върна в темата. Но не насмогвам с четенето. Ето това което наричаш "логика" е всъщност модела, който следва софтуера. Това е моделирането което имам предвид. Говоря от чисто техническа гледна точка, без разните бизнес UML шитни. Моделирането чрез обособяване на отделни части освен целта да направи софтуера по-добре структуриран, организиран, портируем, по-лесен за интегриране в друг проект и по друго време. Освен всички тези аспекти на софтуера, имаме и това което много програмисти наричат "логиката на програмата". Понякога това е само мисловен модел (понякога само в една глава  ). Но ако софтуера е добре структуриран и организиран, този модел може да се "прочете" дори просто с разглеждане на сорсовете. Няма нужда от дълги фермани. До сега не съм видял добре описан модел, няма езици и средства с които да се опише. Миро, когато казваш "новобранците да надничат и да видят други подходи", ако тези подходи не са в "читаем"/разбираем вид, новобранеца освен да си помисли че е много тъп и нищо не разбира няма какво да научи. Освен да е тъп и новобранец, който просто наднича, ежедневно други хора от други домейни(области) опират до ползване на софтуер който е писан от гуру-та на драйвери и ОС-ове. Не е задължително софтуера да е с вертикално наслоена структура и ползващия(юзъра) да е някъде в абстракциите и приложната част. Понякога е колега който иска да реши специфична задача и не му трябват капсулирани блокчета или както казваш "извратена логика". Добре е да има оставени разплетени краища от където да продължи плетката. Тука с gicho сме на един акъл. Абстракцията не бива да е просто чадър над карантиите. Тази абстракция освен да се мели от компилатор или някаква машина, трябва да се мели и от човешки глави. Трябва да има интерфейс и към хората, които я ползват on design/on integration time. Същноста на интерфейса е да позволи две страни(понякога от несъвместими области) да се свържат помежду си и да общуват. Интерфейс който е мислен едностранно в друго време при други обстоятелства не отговаря на моето определение за интерфейс. POSIX кога е мислен и от кого? Колко вода изтече от тогава? Достатъчен ли е на всекиго за всичко? Разбира се поста ми не е контрапукнт на казаното до тук. Просто една друга "извратена логика" родена от ежедневното ровене и вникване в чужд код и дизайн.
_________________ Най-опасният враг на истината и свободата е мнозинството.
|
| Сря Фев 12, 2020 1:53 pm |
|
|
Кой е на линия |
Потребители разглеждащи този форум: 0 регистрирани и 5 госта |
|
Вие не можете да пускате нови теми Вие не можете да отговаряте на теми Вие не можете да променяте собственото си мнение Вие не можете да изтривате собствените си мнения Вие не можете да прикачвате файл
|
|