xxxmatrixxx 0 3 марта, 2021 Опубликовано 3 марта, 2021 · Жалоба Здравствуйте, уважаемые форумчане возникла необходимость отправлять через USART отладочные сообщения с использованием DMA под контроллер STM32F103(на других контроллерах туже проблему наблюдал, например, на STM32L496) Настройку и конфигурацию осуществлял через STMCube MX, считаю, что все верно сделано: затем переназначил функцию _write(), чтобы сообщения вылетали через USART1: int _write (int fd, char *ptr, int len){ HAL_UART_Transmit(&huart1, (uint8_t*) ptr, len,HAL_MAX_DELAY); return len; } int _read (int fd, char *ptr, int len){ *ptr = 0x00; // Flush the character buffer HAL_UART_Receive(&huart1, (uint8_t*) ptr, 1, HAL_MAX_DELAY); return 1; } вот таким образом все корректно работает, т.е. все символы выводятся на консоль без перетираний и искажений, выполняя вот этот код: printf("\033c\r\n"); fflush(stdout); printf("|||||||||||||||||||||||||||||||||||||||\r\n"); fflush(stdout); printf("Init MCU_PWR Complete\r\n"); fflush(stdout); printf("Size of I2C_REG bitfield = %d)\r\n", sizeof(I2C_Work.Regs.bitfield)); for(i = 0; i < I2C_BUF_SIZE; i++) printf("I2C_BUF[%d] = 0x%x\r\n", i, I2C_Work.Regs.I2C_BUF[i]); printf("Version Program STM32: %d.%d.%d (crc = 0x%x)", I2C_Work.Regs.bitfield.Version.bitfield.Major, I2C_Work.Regs.bitfield.Version.bitfield.Minor, I2C_Work.Regs.bitfield.Version.bitfield.Local, I2C_Work.Regs.bitfield.Version.bitfield.Crc); printf(" (0x%x)\r\n", I2C_Work.Regs.bitfield.Version.full_word); вывод на консоли: Quote ||||||||||||||||||||||||||||||||||||||| Init MCU_PWR Complete Size of I2C_REG bitfield = 20) I2C_BUF[0] = 0x1 I2C_BUF[1] = 0x2 I2C_BUF[2] = 0x3 I2C_BUF[3] = 0x4 I2C_BUF[4] = 0x5 I2C_BUF[5] = 0x6 I2C_BUF[6] = 0x7 I2C_BUF[7] = 0x8 I2C_BUF[8] = 0x9 I2C_BUF[9] = 0xa I2C_BUF[10] = 0xb I2C_BUF[11] = 0xc I2C_BUF[12] = 0xd I2C_BUF[13] = 0xe I2C_BUF[14] = 0xf I2C_BUF[15] = 0x10 I2C_BUF[16] = 0x11 I2C_BUF[17] = 0x12 I2C_BUF[18] = 0x13 I2C_BUF[19] = 0x14 Version Program STM32: 4.3.2 (crc = 0x1) (0x4030201) Calculate CRC Program STM32 = 0x8070605 Start ADC measure Start Timer3 on 1 ms Start Listen on I2C2(ADR = 0x60) IMX_RESET_ON_START: Delay timer on 13000 ms но если код заменить на DMA или через прерываний, то теряются символы, скорее всего из-за перетирания буфера, я попытался дожидаться, когда UART будет полностью свободен и только тогда отправлять данные, но все равно происходит перетирка данных int _write (int fd, char *ptr, int len){ while(huart1.gState != HAL_UART_STATE_READY); HAL_UART_Transmit_DMA(&huart1, (uint8_t*) ptr, len); return len; } вот вывод c DMA или по прерываниям: Quote ||||it MCU_PWR Complete |||||||||||||||| Inze of I2C_REG bitfielSiC_BUF[0] = 0x1 tfield = 20) I2C_BUF[1] = 0x2 I2C_BUF[2] = 0x3 I2C_BUF[3] = 0x4 I2C_BUF[4] = 0x5 I2C_BUF[5] = 0x6 I2C_BUF[6] = 0x7 I2C_BUF[7] = 0x8 I2C_BUF[8] = 0x9 I2C_BUF[9] = 0xa I2C_BUF[11] = 0xc I2C_BUF[12] = 0xd I2C_BUF[13] = 0xe I2C_BUF[14] = 0xf I2C_BUF[16] = 0x11 I2C_BUF[17] = 0x12 I2C_BUF[18] = 0x13 I2C_BUF[19] = 0x14 I2rsion Program STM3Velculate CRC Program STM32 = 0x8070605 (0x4030201) Caart ADC measure am STM32 = 0x8070605 Start Timer3 on 1 mStart Listen on I2C2(AStX_RESET_ON_START: Delay timer onIMX_R ESET_ON_START: Delay timer on 13000 ms я пробовал дожидаться и состояния, когда и UART и DMA_TX_UART в состоянии READY, пробовал управлять флагом, который сигнализирует об окончании передачи, флаг выставлялся в функции void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart), но также не помогло я думаю, проблема в каком-нибудь пустяке, но пока его не смог найти... был ли у кого опыт работы с DMA, при котором терялись, перезаписывались данные, на что мне ориентироваться, чтобы считать, что данные полностью ушли на стороне UART и мне можно заполнять буфер? Спасибо, буду рад любой помощи Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrBearManul 0 3 марта, 2021 Опубликовано 3 марта, 2021 · Жалоба 1 час назад, xxxmatrixxx сказал: олностью ушли на стороне UART и мне можно заполнять буфер? Вызывайте прерывание по завершениею передачи каналом ПДП. Это будет 100%-я гарантия. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xxxmatrixxx 0 3 марта, 2021 Опубликовано 3 марта, 2021 · Жалоба 3 minutes ago, MrBearManul said: Вызывайте прерывание по завершениею передачи каналом ПДП. Это будет 100%-я гарантия. я делал вот так: volatile static uint8_t Uart_Tx_Cmpl = 1; int _write (int fd, char *ptr, int len){ while(Uart_Tx_Cmpl == 0); Uart_Tx_Cmpl = 0; HAL_UART_Transmit_DMA(&huart1, (uint8_t*) ptr, len); return len; } void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { Uart_Tx_Cmpl = 1; } не помогло... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 3 марта, 2021 Опубликовано 3 марта, 2021 · Жалоба 1 час назад, xxxmatrixxx сказал: я делал вот так: Видимо, что такое HAL_UART_TxCpltCallback(), зачем оно и где у вас вызывается - предлагаете угадывать читателям? Тогда уж хоть приз объявите угадавшему. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrBearManul 0 3 марта, 2021 Опубликовано 3 марта, 2021 · Жалоба 1 час назад, xxxmatrixxx сказал: void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) Оно вызывается когда? Это какой-то коллбэк для прерывния последовательного порта? Если так, то неправильно. Прерывания от последовательно порта вызываются по завершению передачи одного (возможно нескольких байт для каких-то модификаций) байта, либо при загрузки этого байта из буфера в сдвиговый регистр. Но в любом случае не по завершению передачи N байт. Прерывание должно быть от ПДП по окончанию транзакции. И тогда всё будет работать ок. 1 минуту назад, jcxz сказал: Видимо, что такое HAL_UART_TxCpltCallback(), зачем оно и где у вас вызывается - предлагаете угадывать читателям? Блин... боюсь это произносить, чтобы в меня тапками не начали кидать, но я терпеть не могу куб... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xxxmatrixxx 0 3 марта, 2021 Опубликовано 3 марта, 2021 (изменено) · Жалоба 45 minutes ago, MrBearManul said: Оно вызывается когда? Это какой-то коллбэк для прерывния последовательного порта? Если так, то неправильно. Прерывания от последовательно порта вызываются по завершению передачи одного (возможно нескольких байт для каких-то модификаций) байта, либо при загрузки этого байта из буфера в сдвиговый регистр. Но в любом случае не по завершению передачи N байт. Прерывание должно быть от ПДП по окончанию транзакции. И тогда всё будет работать ок. Блин... боюсь это произносить, чтобы в меня тапками не начали кидать, но я терпеть не могу куб... STMCube все верно отрабатывает, прерывание возникает по окончании передачи всей пачки, а не одного байта (функция HAL_UART_TxCpltCallback) модифицировал код следующим образом и все заработало: volatile static uint8_t Uart_Tx_Cmpl = 1; int _write (int fd, char *ptr, int len){ Uart_Tx_Cmpl = 0; HAL_UART_Transmit_DMA(&huart1, (uint8_t*) ptr, len); while(Uart_Tx_Cmpl == 0); return len; } void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { Uart_Tx_Cmpl = 1; } но я при этом не добиваюсь того, что хотел, а именно освободить на время передачи по UART процессор от ожидания окончания транзакции по UART, как раз именно while(Uart_Tx_Cmpl == 0); когда стоял в самом начале функции int _write() позволял задерживать выполнение, если транзакция еще не завершена(например, идут 2 или 3 printf подряд), а когда этого не требуется, то просто пропускал... Изменено 3 марта, 2021 пользователем xxxmatrixxx Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xxxmatrixxx 0 3 марта, 2021 Опубликовано 3 марта, 2021 (изменено) · Жалоба Решил проблему следующим образом: #define uart_printf(...) { while(huart1.gState != HAL_UART_STATE_READY); printf(__VA_ARGS__); } int _write (int fd, char *ptr, int len){ HAL_UART_Transmit_DMA(&huart1, (uint8_t*) ptr, len); return len; } вместо printf использую у себя в основной программе uart_printf, причина была в подмене данных printf, т.к. данные передавались в функцию int _write (int fd, char *ptr, int len) по указателю всем спасибо за помощь!!! Изменено 3 марта, 2021 пользователем xxxmatrixxx Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrBearManul 0 3 марта, 2021 Опубликовано 3 марта, 2021 · Жалоба 28 минут назад, xxxmatrixxx сказал: STMCube все верно отрабатывает Печально. Не куб должен отрабатывать, а вы. Ну да ладно. 28 минут назад, xxxmatrixxx сказал: а именно освободить на время передачи по UART процессор от ожидания окончания транзакции по UART Используйте такую штуку как ОСРВ и всё получите. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ozone 2 4 марта, 2021 Опубликовано 4 марта, 2021 · Жалоба Почему использование библиотек HAL считается постыдным? В то же время использование ОСРВ это норм? ОСРВ это такой же уровень абстракций. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 34 4 марта, 2021 Опубликовано 4 марта, 2021 · Жалоба 54 минуты назад, Ozone сказал: Почему использование библиотек HAL считается постыдным? В то же время использование ОСРВ это норм? ОСРВ это такой же уровень абстракций. Почему постыдным? Используйте, но вы должны понимать, что происходит в функциях, которые вы вызываете, в большинстве своем, те, кто используют куб даже не догадываются, что там происходит, отсюда непонятки и глупые вопросы... ОСРВ тоже нужно использовать не где попало и абы как... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrBearManul 0 4 марта, 2021 Опубликовано 4 марта, 2021 · Жалоба 1 час назад, Ozone сказал: Почему использование библиотек HAL считается постыдным? Не является. Я и сам их использовал в своё время немного. Вот только от необходимости понимания "физики процесса" это не освобождает. Особенно тогда, когда понимаешь, что либа содержит ошибку. А исправить её ты не можешь. Некоторые же люди надеются на "хал" как на нечто безошибочно работающее, но, главным образом, освобождающее от необходимости изучать тонны документации на сам процессор, микроархитектуру и периферию микроконтроллера. Это и приводит к тому, что задаётся масса вопросов, которые демонстрируют отсутствия понимания и желания разобраться самостоятельно. Я же, направившись с ошибками в "хале" и прочих подобных либах, понял, что проще писать драйвера периферии самостоятельно. В любом случае с документацией разбираться нужно. Зато есть плюсики: 1. Сможешь оперативно править ошибки. 2. Без проблем добавишь необходимые функции. 3. Ты растёшь профессионально и можешь оставаться конкурентноспособным, если это важно) 4. Ты можешь очень умно отвечать на форуме и своим коллегам))))))) 1 час назад, Ozone сказал: В то же время использование ОСРВ это норм? ОСРВ и HAL не взаимоисключают другу друга. И вообще на друг друга не влияют. Если вы знаете, для чего используется ОСРВ и что она содержит, вы бы поняли, почему я посоветовал её автору топки. Тем не менее, я могу это сделать и без ОС . И делал. Но с ОСРВ гораздо удобнее! 1 час назад, Ozone сказал: ОСРВ это такой же уровень абстракций. Нет. Это, прежде всего, инструмент, который позволят вам использовать многозадачность. Например, вытесняющую. А также несколько средств межпроцессного взаимодействия. Можете и без неё обходиться. Тут уж кто как считает нужным. И потом. Не каждую ОСРВ я советую на форуме: например, FreeRTOS и scmRTOS известны очень давно. С начала 2000-х годов. За это время они "вылизаны" до безобразной чистоты) И их код надёжен. Разработчики scmRTOS находятся на этом форуме, и, при необходимости, могут оперативно ответить на вопросы. Те, кто ковырялся в потрохах FreeRTOS и дорабатывал её, тоже здесь обитают) Так что...) Плюс эти системы идут даром, что немаловажно в некоторых случаях. В остальных я бы посоветовал ucOS/2. 15 минут назад, mantech сказал: отсюда непонятки и глупые вопросы... Люто, дико и громко плюсую! 15 минут назад, mantech сказал: ОСРВ тоже нужно использовать не где попало и абы как... +1. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xxxmatrixxx 0 7 марта, 2021 Опубликовано 7 марта, 2021 · Жалоба я смотрю вопрос касался одного, а переключился опять в использование куба или нет... я всегда буду его использовать, т.к. точка входа в программирование STM32, благодаря ему, у меня заняло около 30 мин, я начал практически сразу писать функционал, при этом: 1. мне не надо было лезть в изучение всей периферии контроллера 2. изменение конфигурации и состава периферии при неизменном функциональном коде проходит за 1 мин 3. очень удобно, когда работаешь сразу с несколькими контроллерам STM32 разных семейств(у меня, например, STM32F103, STM32F107, STM32F407,STM32L496) согласен, что надо понимать, что и откуда берется, но лезть туда надо: 1. когда не работает задуманое 2. работает, но с косяками, либо слишком медленно к такому же подходу я стремлюсь при разработке IP Core на ПЛИС, чтобы была универсальность при написании драйвера под ОС для работы с модулями, реализованных на ПЛИС самое главное, что вы экономите время, CUBE имеет косяки, например, пришлось мне обходить косяк с работой по SDMMC, сгенерированный кубом, но я на это убил 2 дня, да пришлось во всем разобраться, но ничего страшного... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 7 марта, 2021 Опубликовано 7 марта, 2021 · Жалоба 3 часа назад, xxxmatrixxx сказал: я смотрю вопрос касался одного, а переключился опять в использование куба или нет... я всегда буду его использовать, т.к. точка входа в программирование STM32, благодаря ему, у меня заняло около 30 мин, я начал практически сразу писать функционал, при этом: 1. мне не надо было лезть в изучение всей периферии контроллера Вот потому и торчите который день на этом входе, в который "за 30 мин" вошли. Не умея решить даже такой элементарный вопрос. И так и будете торчать на входе, спотыкаясь на простейших вещах, если не будете изучать периферию. А если вместо кубодрочерства изучать периферию, то таких затыков на ровном месте даже не возникает. 3 часа назад, xxxmatrixxx сказал: 2. изменение конфигурации и состава периферии при неизменном функциональном коде проходит за 1 мин Ну-ну... Оно и заметно как это "за 1 мин" у вас уже много дней продолжается. PS: Учите матчать! Без этого в программировании МК делать нечего. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 34 7 марта, 2021 Опубликовано 7 марта, 2021 (изменено) · Жалоба 9 часов назад, xxxmatrixxx сказал: благодаря ему, у меня заняло около 30 мин, я начал практически сразу писать функционал Да, да, мы тут сидим месяцами изучаем внутрянку МК, как с ней работать, а тут нате)))))))) Еще раз - если вы за 30 минут установили прогу, скомпилировали демо-программку, которая умеет загружаться, мигать диодом и чего-то там выдавать в уарт или эзернет - это просто демо программа, и ни о каких ваших знаниях она не говорит, я уверен, что и после этого, МК для вас - это такой уменьшенный компьютер, который можно запрограммировать за полчаса, на чем угодно, типа визуалбейсика или какого-нить яваскрипта, или например, хочу с ДМА чтоб работало - так ерунда, просто ищем галочку "включить ДМА" и не паримся))), но это совсем не так... Ну а если уж так хочется не думать о периферии, и программировать на более высоком и универсальном уровне - то надо выбирать какой-нить фреймворк или переходить на линукс, тут без вариантов, ИМХО. 5 часов назад, jcxz сказал: Учите матчать! Без этого в программировании МК делать нечего. +1 Изменено 7 марта, 2021 пользователем mantech Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrBearManul 0 8 марта, 2021 Опубликовано 8 марта, 2021 · Жалоба 15 часов назад, xxxmatrixxx сказал: у меня заняло около 30 мин Это иллюзия, как опиумный дым. 15 часов назад, xxxmatrixxx сказал: но лезть туда надо: Самое интересное, что если залезть туда раньше, то, скорее всего, у вас ситуация "не работает как надо" встретится с вероятностью 10% вместо 80%. Из личного опыта и опыта коллег. Впрочем, вы взрослый человек и переубеждать вас нет смысла))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться