Jump to content

    

pokk

Участник
  • Content Count

    187
  • Joined

  • Last visited

Community Reputation

0 Обычный

About pokk

  • Rank
    Частый гость

Recent Profile Visitors

2404 profile views
  1. Ну вот же на первом шаге, конфликт возникает если клиента другой клиент перебьет, в момент модификации confing. Под клиентом я понимаю задачу клиент freertos. Да из задач, одна задача вызывается, когда пользователь физически кнопку ок нажал в меню, а вторая задача вызывается, когда прилетел WEB запрос. Но это так частный случай, пока интересуюсь как в общем это разрулить.
  2. И как это происходит в предложенно вами третьем варианте ?
  3. Ну вы же сами все правильно написали Именно из за этого и хочу их разделить.
  4. Для атомарного доступа к переменной confing В том то и дело клиентов несколько может быть и они все могут модифицировать confing
  5. Вообще то нет, это я описал функцию модификацию параметра на клиенте. Если флаг был сброшен, то модифицируем параметр, иначе ждем когда флаг сброситься.
  6. А можно по подробнее как это используеться? Если использовать в лоб то это как то так char volatile flag; void ModConfing(void){ //------------------------------------ while(1){ // ожидаем флаг if(flag==1){ break; }else{ taskYIELD(); } } //------------------------------------ //изменение конфигурации //------------------------------------ flag=0; } не вижу чем отличаеться от mutex, он даже проше. А в чем преимущество такого разделение ? Что задачи клиенты не будут подтупливать на момент записи ? Это да запись идет всем блоком, я про такой момент ModAndSaveConfing(VAR1,100); ModAndSaveConfing(VAR2,100); ModAndSaveConfing(VAR3,100); на такой случий надо отдельные функции модификации городить confing.var1=100; confing.var2=200; confing.var3=300; SaveConfing();
  7. Флаг занятости, это же mutex? А зачем выделять функцию записи в отдельную задачу?
  8. В том то и дело, что эти процессы не сильно то и повторяющиеся, их вызывает пользователь когда нажимает кнопки в меню и в web странице. По этому и решил сразу же в этих обработчиках сделать запись конфигурации в память(внешнуюю), а если все таки наложаться, то по семафором должно все разрулиться.
  9. Что бы корректно произошла модификация параметра, ведь его может модифицировать другая задача. Хотя да, для одного и того же параметра наврятли, но структура модифицировать из другой задачи точно может.
  10. Задача такая, есть несколько обработчиков вызываемые через FREERTOS из разных задач. В них должна происходить модификация параметра и запись всей структуру конфигурации в память. Из за того что обработчики вызываются из разных задач, что бы не было переключение контента при модификации параметра его надо заблокировать через mutext. Первое что приходит на ум в лоб xSemaphoreTake(xConfing,portMAX_DELAY); confing.var1=100; confingClcCrc(); SaveConfing(); xSemaphoreGive(xConfing); Но такой вариант не нравиться (загромождает логику). Потом подумал завернуть это все в функцию типа такого: SaveConfing(&confing.var1,100); В принципе, уже более понятно, но тут другая проблема вылезла, функций надо большое количество под каждый тип под массив, под одинарную переменную, а если надо записать больше 1 параметра в одном вызове ? Не гонять же всю структуру в память после каждого байт. В общем подскажите, как это делается что бы было удобно? Или набор функций каких используете ? Была мысль, что бы, передавать сохраняемые данные в одну задачу через очереди, а там производить, модификацию конфигурации + запись. Но отказался от такого нагромождения из за того что, очень малая вероятность, что два обработчика вызовутся одновременно.
  11. Все понял, да походу к данным проще добавить CRC, чем внутри записи его реализовывать А что тут находиться ? Как то тут много типов на увеличенный размер шифрованных данных. Нет нет, я про блок данных (конфигурации/журнала), допустим что было записано 5 аварий(разными блоками COBS) и теперь их надо прочитать, т.е с начала надо прочитать последнюю, аварию(блок COBS), и потом продолжить считать в глубь. И где производить сброс, что при следующий итерации считывание всех 5 аварий, надо считывать с начала, записи а не продолжать, считывать из глубины.
  12. А как добавить CRC в кадр с минимальным, копирование данных ? (без промежуточного буфера) Да походу только так, а я губу раскатал, что так как работаем с потоком байт, то и высчитывать CRC по байтно , в момент кодирование. PS: А функцию считывание с какими параметрами запускаете ? Интересует момент, как сделан выбор продолжить считывания 2-3 блока или надо сбросить и начать с 1 блока.
  13. jcxz, Можете подсказать как у вас идет кодирование CRC ? Сделал кодирование данных в COBS и запись, считывание и декодирование. Кодирование COBS, сделал следующим образом, так как все данные известны, то при начальном вхождении пробегаюсь по массиву данных и нахожу позицию 0, и его выдаю из функции кодирования. Когда начил добавлять CRC возникла проблема что его нету в данных по которым идет кодирование, соответственно COBS отрабатывает не совсем корректно. Решение есть простое, перед тем как кодировать, посчитать в цикле CRC и добавить в конец данных, но не хотелось бы заморачиваться на увеличение данных под CRC когда закидываешь данные на запись. Вот что получилось: // массив данных TestDataWrite50 который надо записать, количество байт 50, суда совсем не хотелось влазить что бы выделять место под CRC StreamWriteDataFlash(TEST1,TestDataWrite50,50); Вот как я планировал сделать, но в данном случае CRC не правильно добавляется (Шапка COBS указывает на конец блока в 50 байт, без учета CRC) //================================================================================================== /* * @Описание: * @Параметр: * @Возврат: */ void StreamWriteDataFlash(uint8_t name,uint8_t *data,uint16_t lenght){ uint8_t Temp; uint8_t LenBalance; uint8_t Tempdata; uint32_t CRC32=0; uint16_t LenCobs=0; //------------------------------------------------ ResetCrc(); //------------------------------------------------ LenCobs=InitCodeCOBS(data,lenght); //------------------------------------------------ CalcShiftHead(name,LenCobs); //------------------------------------------------ for(int16_t i = 0; i<lenght;i++){ //------------------------------------------------ Tempdata=data[i]; Tread_CRC(Tempdata); // CRC //------------------------------------------------ Cobs_encode(Tempdata); // COBS //------------------------------------------------ if(IsCobsCacheFull()){ Temp=PopCobsCache(); Temp=~Temp; PutDataInFlashCache(name,Temp); Temp=PopCobsCache(); Temp=~Temp; PutDataInFlashCache(name,Temp); } } //------------------------------------------------ LenBalance=GetByteInCobsCache(); if(LenBalance>0){ for(uint8_t i=0;i<LenBalance;i++){ Temp=PopCobsCache(); Temp=~Temp; PutDataInFlashCache(name,Temp); } } //------------------------------------------------ //CRC32=GetCRC(); CRC32=~0xAABBCCEE; //------------------------------------------------ //----------В COBS буфер на 4 байта--------------- //------------------------------------------------ Tempdata=CRC32>>24; Cobs_encode(Tempdata); Tempdata=CRC32>>16; Cobs_encode(Tempdata); Tempdata=CRC32>>8; Cobs_encode(Tempdata); Tempdata=CRC32; Cobs_encode(Tempdata); if(IsCobsCacheFull()){ Temp=PopCobsCache(); Temp=~Temp; PutDataInFlashCache(name,Temp); Temp=PopCobsCache(); Temp=~Temp; PutDataInFlashCache(name,Temp); Temp=PopCobsCache(); Temp=~Temp; PutDataInFlashCache(name,Temp); Temp=PopCobsCache(); Temp=~Temp; PutDataInFlashCache(name,Temp); } //------------------------------------------------ PutDataInFlashCache(name,(uint8_t)~0); // Разделитель !!!!!!!! WriteCache_sync(name); //------------------------------------------------ }
  14. Подскажите, как ваш алгоритм на абстракции (модули) делиться. Сначала у меня возникали трудности с адресацией страницы, секторов ... но потом представил что у флеша, есть буфер FIFO(кэш) размером 255 байт, и реализацию его вынес в модуль кэш, и все дальнейшие взаимодействия идут уже на основе функций из этого модуля. void PutDataInFlashCache(uint8_t name,uint8_t data); uint8_t GetDataFromFlashCache(uint8_t name); Так вот теперь встал вопрос, где должен находиться алгоритм с кольцевым буфером ? перед кэш ? или работать на основе кэш ? Если перед кэшом, то как-то все мудрено получается, совсем не представляю как это должно выглядеть. Если алгоритм с кольцевого буфера работает на основе кэша, то тут как бы проще, тогда у кольца получается своя байтова линейная адресация допустим от 0 до 409600 (100 секторов по 4096) байтов (естественно с перебросом адреса в 0 при увеличении ядреса > 409600 ). Но тогда где разместить весь алгоритм стирания сектора дырка, и вообще как кэш завернуть по кольцу. В общем подразумеваю структуру модулей примерно такую: Физические адреса Flash -> кэш -> кольцевой буфер -> файловая система (проверка CRC, шифрование COBS)
  15. Там у вас 4 байта, маркер занятости все 4 байта занимает? Или есть что-то еще? А то я так же заложил 4 байта и только в 1 поставил маркер, а остальные пока не используются, но периодически руки так и чешутся что бы что нибудь туда добавить(подумывал добавить информацию по битно, на записанные страницы, для более быстрого и простого поиска головы), но оказалось это лишнее, голова и так достаточно просто ищется.