Alex_Golubev 0 13 октября, 2020 Опубликовано 13 октября, 2020 · Жалоба Вопрос к Гуру. Меня интересуют методы реализации какие наиболее оптимальные и простые в понимании, с помощью которых можно допустить меньше количество ошибок и наиболее устойчивые в работе. пошаговое объяснение работы протокола змодем. Понял не все, надеюсь пойму. Прием файла ---> * 1. ---> Получаю команду RZ+CR в числовом виде в .hex формате 72 7A 0D * 2. ---> Получаю запрос "Так называемый ZRQINIT" в .hex формате 2A 2A 18 42 30 30 30 30 30 30 30 30 30 30 30 30 30 30 8D 8A 11 раскладывается по HEX HEADER "* * ZDLE B TYPE F3/P0 F2/P1 F1/P2 F0/P3 CRC-1 CRC-2 CR LF XON" причем 8D 8A в xor операции * 3. <--- Я должен ответить на запрос "ZRQINIT" отвечаю в HEX формате (взял за основу HEX формат) "2A 2A 18 42 30 31 30 30 30 30 30 30 32 33 62 65 30 0D 8A" причем самое интересное может прийти запрос а может и не прийти запрос нужно обрабатывать два события * 4. ---> Получаю запрос "ZFILE" с заголовком названия файла сначала получаю "2A 18 41 04 00 00 00 01 99 27" После сразу приходит "68 65 6C 6C 6F 77 6F 72 6C 64 2E 74 78 74 00 31 37 20 31 33 37 33 36 37 33 36 32 35 34 20 31 30 30 36 34 34 00 18 6B 18 51 4A" * 5. <--- После сразу отвечаю ZPAD отправляю посылку "2A 2A 18 42 30 39 30 30 30 30 30 30 30 30 61 38 37 63 0D 8A" * 6. ---> Получаю данные файл в .bin формате "68 65 6C 6C 6F 20 77 6F 72 6C 64 21 21 21 21 21 21 18 68 B3 94" в конце контрольная сумма Crc16 * 7. ---> В силу короткого файла получаю конец файла "ZEOF" "2A 2A 18 42 30 62 31 31 30 30 30 30 30 30 38 31 65 63 8D 8A 11" * 8. <--- Отвечаю в .bin формате "2A 2A 18 42 30 31 30 30 30 30 30 30 32 33 62 65 30 0D 8A" * 9. ---> Принимаю пакет ZFIN "2A 2A 18 42 30 38 30 30 30 30 30 30 32 33 62 65 30 0D 8A" * 10. <--- Отвечаю ZFIN "2A 2A 18 42 30 38 30 30 30 30 30 30 32 33 62 65 30 0D 8A" * 11. ---> Получаю два символа "OO" * * Проблемы: * 1. Использую виртуальный ком порт на stm32. По виртуальному ком порту может прийти от 1 байта до 64 байт. Пример может сразу прийти RZ+CR или сначала R потом Z потом CR * 2. Обрабатываю входную информацию в векторе прерывания USB * 3. Высылаю данные ответа через USB * Есть идеи как лучше это реализовать на си ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Herz 4 13 октября, 2020 Опубликовано 13 октября, 2020 · Жалоба 14 minutes ago, Alex_Golubev said: Есть идеи как лучше это реализовать на си ? Наверняка есть. Я не "гуру" в С, но меня всегда огорчают подобные вопросы. Покажите сначала свою идею. Начните с чего-то. Попробуйте вообще реализовать это на С. А тогда Вам уже подскажут, "как лучше", укажут на ошибки. Вы же на рассчитываете здесь получить готовое решение, просто озвучив проблемы? А то звучит как: "я-то знаю, как реализовать. Но желаю совершенства. Может, у кого есть идеи получше"? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alex_Golubev 0 13 октября, 2020 Опубликовано 13 октября, 2020 · Жалоба Я написал тестовую программу когда изучал протокол. Но мне она очень не нравится ищу варианты более правильного кода. вот тест: Скрытый текст if(UserRxBufferFS[0] == 'r' && UserRxBufferFS[1] == 'z' && UserRxBufferFS[2] == CRZmodem){ // если пришла команда c zmodem "rz" + cr comandeZmodem = 1; // устанавливаем флаг что пришла команда, дабы на следующем вызове прерывания произошел вход в обработчик входного пакета данных HEADERFile = 0; // сброс всех основных флагов DataFile = 0; counteFile = 0; // счетчик принимаемого файла OO = 0; // сброс флага конца приема данных } if(HEADERFile){ // если устанавился флаг приема заголовочных данных uint16_t i = 0; uint16_t conterChar = 0; for(i = 0; i < *Len; i++){ if(UserRxBufferFS[i] != ZDLE){ bufUsb[conterChar++] = UserRxBufferFS[i]; } else{ if(UserRxBufferFS[i] == ZDLE){ if((UserRxBufferFS[i + 1] & 0x60) == 0x40){ UserRxBufferFS[i + 1] &= 0xbf; bufUsb[conterChar++] = UserRxBufferFS[i + 1]; i = i + 1; } } } }// наложена маска на первый байт crc 16 в случаи приема в hex формате if(!rZModem_crcUpdate(bufUsb,conterChar)) { asm("nop"); // тест } rZModem_sendHexHeader(ZRPOS); // ответ на загаловок HEADERFile = 0; // сброс флага о готовности взятия загаловка } if(DataFile){ // прием файла максимальная длина файла по протоколу zmodem 1024 байта if(counteFile < 1024){ for(uint16_t i = counteFile; i < counteFile + *Len; i++){ bufUsb[i] = UserRxBufferFS[i]; } } else{ DataFile = 0; } counteFile += *Len; } if(comandeZmodem){ // если пришла команда rz+cr if(UserRxBufferFS[0] == 'o' && UserRxBufferFS[1] == 'o' && OO){ comandeZmodem = 0; OO = 0; } if(UserRxBufferFS[0] == ZPAD && UserRxBufferFS[1] == ZPAD && UserRxBufferFS[2] == ZDLE && UserRxBufferFS[3] == ZHEX){ // hex формат "ZPAD , ZPAD, ZDLE, ZHEX" if(UserRxBufferFS[18] == (CRZmodem^0x80) && UserRxBufferFS[19] == (LF^0x80) && UserRxBufferFS[20]== XON) // пришли последнее команды говорящие о конце покета { uint8_t bufcomand[7]; memset(bufcomand,0,sizeof(bufcomand)); // убираю какахи из буфера for(uint8_t i = 0; i < 7; i++){ bufcomand[i] = rZModem_getNextHexCh(UserRxBufferFS[4 + i*2], UserRxBufferFS[4 + i*2 + 1]); // 4 5 6 7 8 9 10 11 12 13 14 15 16 17 } if(!rZModem_crcUpdate(bufcomand,7)){ if(bufcomand[0] == ZRQINIT){ rZModem_sendHexHeader(ZRINIT); // ответ на ZRINIT } if(bufcomand[0] == ZEOF){ // по суте как понял присылается в конце после передачи файла rZModem_sendHexHeader(ZRINIT); // ответ на ZEOF } if(bufcomand[0] == ZFIN){ rZModem_sendHexHeader(ZFIN); // ответ на ZFIN OO = 1; } } else{ comandeZmodem = 0; // не сошлось crc начинаем сначала } } } else if(UserRxBufferFS[0] == ZPAD && UserRxBufferFS[1] == ZDLE && UserRxBufferFS[2] == ZBIN){ // bin формат uint8_t bufcomand[7]; uint8_t counterComand = 0; uint8_t j = 7; memset(bufcomand,0,sizeof(bufcomand)); // убираю какахи из буфера for(uint8_t i = 0; i < j; i++){ // на случай если получил иинвернтированый дюбильный zdle, нах он нужен? if(UserRxBufferFS[i + 3] != ZDLE){ bufcomand[counterComand++] = UserRxBufferFS[i + 3]; } else{ if(UserRxBufferFS[i + 3] == ZDLE){ if((UserRxBufferFS[i + 1 + 3] & 0x60) == 0x40){ UserRxBufferFS[i + 1 + 3] &= 0xbf; bufcomand[counterComand++] = UserRxBufferFS[i + 1 + 3]; i = i + 1; j = j + 1; // пока не придумал более лучшей вариант но охота счетчик j убрать иногда приходит zdle зачем не ясно } } } } if(!rZModem_crcUpdate(bufcomand,7)){ if(bufcomand[0] == ZFILE){ HEADERFile = 1; } if(bufcomand[0] == ZDATA){ DataFile = 1; counteFile = 0; // обнуляем счетчик длины приемного буфера файла } } else{ comandeZmodem = 0; // не сошлась crc начинаем сначала } } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gosha-z 2 13 октября, 2020 Опубликовано 13 октября, 2020 · Жалоба Z-Modem чтоль? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
arhiv6 14 13 октября, 2020 Опубликовано 13 октября, 2020 · Жалоба Подобные вещи решаются с помощью Конечных Автоматов. У Вас есть несколько состояний (ожидание RZ+CR, ожидание ZRQINIT, ожидание ZFIN и т.п.) и условий, по которым автомат переходит из одного состояние в другое (определённая последовательность байт или т.п.). 1) Почитайте про конечные автоматы, на листочке постройте граф переходов для разбора вашего протокола 2) Посмотрите как конечные автоматы на реализуются на СИ (на swich/case или на таблице переходов) 3) Реализуйте построенный граф на Си Например, можете посмотреть на WAKE - там в функциях Port_Read и Port_Write на конечных автоматах (на основе swich/case) разбор протокола сделан. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mdmitry 0 13 октября, 2020 Опубликовано 13 октября, 2020 · Жалоба Есть программы (пакеты) для linux с поддержкой zmodem. Посмотрите исходники lrzsz или minicom. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alex_Golubev 0 14 октября, 2020 Опубликовано 14 октября, 2020 · Жалоба Я почитал теорию и подумываю использовать автомат с магазином памяти. Как понял он полностью покрывает приём передачу файла, и приём передачу команд для работы с терминалом. Может у кого есть боевая реализация на си? Или может подсказать где взять можно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться