Перейти к содержанию
    

Polaris

Свой
  • Постов

    299
  • Зарегистрирован

  • Посещение

Весь контент Polaris


  1. А если так: AT+HTTPPARA="URL","http://xxxxxxxxx.ru:80/?id=123" Номер порта должен все-таки за именем следовать, а не за запросом.
  2. Согласен, не вижу смысла гадить в каталог с исходниками, даже если это делает CMake
  3. Не уверен по этому поводу, потому что если он где-то и находится, то make его сразу же после ошиьки стирает. Но предполагаю, что находится он действительно в bin. На другом форуме обратили внимание на то, что arm-none-eabi-size обращается к ${EXECUTABLE}, который предполагается найти в корне, поэтому нужно обращаться к ./bin/${EXECUTABLE}. Но я выяснил еще одну вещь - даже если такой подход сработает, то все равно основная работа будет вестись в корне, чего мне не хотелось бы, проблема тут больше с запуском cmake. Я это делал вот так: cmake -G "MinGW Makefiles" -DCMAKE_TOOLCHAIN_FILE=arm-none-eabi-gcc.cmake mingw32-make Теперь же делаю вот так: cmake -G "MinGW Makefiles" -DCMAKE_TOOLCHAIN_FILE=arm-none-eabi-gcc.cmake . -Bbin cmake --build ./bin Теперь вся служебная информация оказывается в bin, включая и генерируемые map, hex, bin
  4. Вот полный текст CMakeLists.txt: cmake_minimum_required(VERSION 3.5) project(xxx) enable_language(C ASM) set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS OFF) set(EXECUTABLE ${PROJECT_NAME}.out) include_directories(src) set(sources src/main.c ) add_executable (${EXECUTABLE} ${sources}) target_compile_definitions(${EXECUTABLE} PRIVATE -D__ATSAMC21E18A__ -D__TARGET_CPU_CORTEX_M0 ) target_compile_options(${EXECUTABLE} PRIVATE -mcpu=cortex-m0plus -march=armv6-m -mthumb -mfloat-abi=soft -fdata-sections -ffunction-sections -fno-strict-aliasing -Wall -O2 ) target_link_options(${EXECUTABLE} PRIVATE -Tsys/samc21g18a_release.ld -mcpu=cortex-m0plus -march=armv6-m -mthumb -mfloat-abi=soft -Wl,-Map=${PROJECT_NAME}.map,--cref -specs=nano.specs -Wl,--gc-sections -lm -lc -lnosys ) target_link_libraries(${EXECUTABLE} PRIVATE m ) add_custom_command(TARGET ${EXECUTABLE} POST_BUILD COMMAND arm-none-eabi-size ${EXECUTABLE}) add_custom_command(TARGET ${EXECUTABLE} POST_BUILD COMMAND arm-none-eabi-objcopy -O ihex ${EXECUTABLE} ${PROJECT_NAME}.hex COMMAND arm-none-eabi-objcopy -O binary ${EXECUTABLE} ${PROJECT_NAME}.bin)
  5. Та же ситуация, каталог создан, но пуст, ошибка та же.
  6. Пытаюсь заставить собираться проект под Cortex-M0+ при помощи GCC и CMake, в принципе, все получается, но один момент никак не хочет работать так, как нужно мне. Мне хотелось бы, чтобы результат работы линкера сбрасывался не в корень проекта, где лежит CMakeLists.txt, а в подкаталог проекта, например, в bin. Пишу что-то такое: #set(CMAKE_RUNTIME_OUTPUT_DIRECTORY bin) Каталог bin в результате прогона make создается, но он пуст, а прогон make дает следующую ошибку: [100%] Linking C executable bin\xxx.out arm-none-eabi-size: 'xxx.out': No such file mingw32-make[2]: *** [CMakeFiles\xxx.out.dir\build.make:913: bin/xxx.out] Error 1 mingw32-make[2]: *** Deleting file 'bin/xxx.out' mingw32-make[1]: *** [CMakeFiles\Makefile2:82: CMakeFiles/xxx.out.dir/all] Error 2 mingw32-make: *** [Makefile:90: all] Error 2 Если убрать определение CMAKE_RUNTIME_OUTPUT_DIRECTORY, то все работает, но файлы бросаются в корневой каталог, что неудобно. В чем может быть проблема? В данный момент я работаю с Windows и mingw.
  7. Да, и чтобы два раза тему не открывать, у меня тут тоже проблемка нарисовалась с ADC. Раньше я всегда использовал только ADC0, теперь стало необходимо опрашивать несколько каналов с ADC0, а ADC1 запускать на конвертацию сразу целого блока по DMA. Все вроде бы хорошо, но выяснилось, что теперь при обращении к ADC0, когда я меняю канал измерения, код виснет на ранее совершенно безопасной строчке. /**< Disable ADC */ channel->CTRLA.bit.ENABLE = 0; while (channel->SYNCBUSY.reg & ADC_SYNCBUSY_ENABLE); /**< Set channel */ channel->INPUTCTRL.bit.MUXPOS = input; /**< Enable ADC */ channel->CTRLA.bit.ENABLE = 1; while (channel->SYNCBUSY.reg & ADC_SYNCBUSY_ENABLE); /**< Reset ready flag */ channel->INTFLAG.reg |= ADC_INTFLAG_RESRDY; /**< Start conversion */ channel->SWTRIG.bit.START = 1; Строчка эта: Отладчик показывает, что в SYNCBUSY бит ENABLE больше не сбрасывается. Если отключить ADC1, то все работает нормально. Очень странно, что одна инстанция так влияет на другую. Вроде бы в эррате ничего про подобные коллизии нет. Если вдруг кто имеет объяснение этому поведению - буду рад послушать.
  8. Если есть инкремент в назначении или источнике, то нужно модифицировать адрес, dmadescr.BTCNT.reg = DMAC_BTCNT_BTCNT(4); будет недостаточно, нужно еще сделать: dmadescr.DSTADDR.reg = (uint32_t) &adcresult; descriptor.DSTADDR.reg += 4 * sizeof(uint16_t); В даташите стоит: DSTADDR[31:0] Transfer Destination Address This bit group holds the destination address corresponding to the last beat transfer address in the block transfer. Уж не знаю, зачем они это сделали, но у меня работает.
  9. Ставил, эффект нулевой, что работает с третьим, не работает с первым.
  10. Аналогичная ситуация, STM32F446, ADC_ExternalTrigConv_T1_CCх не захотел работать ни под каким соусом.
  11. Да, интересный факт, я там даже не искал, смотрел исключительно главу про CAN. Но на самом деле у меня ревизия E, так что, думаю, поправили не слишком хорошо. Но с их качеством документации оно и неудивительно.
  12. Да, с землей есть такое, но суть оказалась не в этом. Проблема была в слишком большом разбросе частот у висящих на шине устройств, для такой скорости в ATSAMC21 нельзя использовать PLL, у него точность оказалась даже ниже, чем у внутреннего генератора, когда запитал ядро от внутреннего, а CAN от внешнего кварца без всякого умножителя, проблема исчезла начисто. Но все равно спасибо за идею!
  13. Занимаюсь реализацией самописного протокола для CAN на ATSAMC21, в целом все понятно и четко, скорость работы - 500 кбит/с. Для отладки и управления со стороны компьютера использую CAN-USB адаптер от Kvaser. Вроде бы все работало, начал смотреть, что там происходит на шине и обнаружил достаточно большое количество Error frames. Причем обнаруживаются они только в том случае, когда на шине более одного участника. Если к адптеру подключена одна плата - все хорошо, подключаешь вторую - до одного процента пакетов испорчены. Выглядит это вот так: Зеленый канал - это состояние питания микроконтроллера, желтый - сама шина. Второй участник при этом совершенно точно ничего не передает, я специально становился в отладке на функцию передачи - она ни разу не вызывалась. Кабель достаточно короткий, с обеих сторон терминирован 120 Ом. Как видно из скриншотов, выброс связан с искажение бита ACK, но кто это может делать - я совершенно не понимаю. Фильтры на участниках настраивал и таким образом, чтобы отбрасывать чужие пакеты, ничего не дало, в принципе, и не должно было дать, это же ACK. Что бы это могло быть?
  14. Нет, на Нордике вполне можно организовать собственный протокол или использовать их же минималистичный Shockburst, вся работа радио там доступна для управления на достаточно высоком уровне.
  15. Проблема решена, вопрос был в логике ожидания получения байта: while ((DMA2_Stream1->CR & DMA_SxCR_EN) || (WaitingRxUART == true)) Изменение порядка условий все решило.
  16. STM32F446 и DMA для вывода на GPIO

    Доброго всем времени суток. Столкнулся тут со странным поведением DMA у STM32F446 при использовании DMA2 для комутации GPIO. Необходимость возникла из-за того, что на новой плате не были предусмотрены инвертеры уровня UART, а ведомое устройство в режиме загрузчика их, как оказалось, требует. С STM32F302 проблем бы не было, там есть инверсия уровней, но вот в более быстром и сложном F446 такой инверсии нет, плату переделывать не хотелось, пришлось искать решение в виде софтового UART на DMA. В плане передачи проблем никаких нет, все работает, тайминги и уровни не вызывают никаких вопросов, а вот в плане приема бьюсь уже неделю. Вот так выглядит инициализация DMA: static uint32_t Buff[128]; DMA_DeInit(DMA2_Stream1); DMA_StructInit(&DMA_InitStructure); DMA_InitStructure.DMA_BufferSize = 0; DMA_InitStructure.DMA_Channel = DMA_Channel_7; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&Buff; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(GPIOA->IDR); DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; DMA_Init(DMA2_Stream1, &DMA_InitStructure); Вот так инициализирую таймер, который будет задавать тактовую частоту (57600): TIM_DeInit(TIM8); TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Period = TIMER_PERIOD - 1; TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(SystemCoreClock / 1 / TIMER_FREQ) - 1; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure); TIM_GenerateEvent(TIM8, TIM_EventSource_Update); TIM_Cmd(TIM8, ENABLE); TIM_DMACmd(TIM8, TIM_DMA_Update, ENABLE); Частоты однозначно верные, потому что тот же таймер используется для передачи, а там все ок, как в плане приема на стороне прибора, так и на осциллографе. И вот так происходит прием: uint8_t i; uint8_t val = 0; /**< Empty buffer */ memset(Buff, 0, 10); DMA_Cmd(DMA2_Stream1, DISABLE); DMA_ClearFlag(DMA2_Stream1, (DMA_FLAG_TCIF1 | DMA_FLAG_HTIF1 | DMA_FLAG_TEIF1)); /**< Activate edge interrupt */ WaitingRxUART = true; EXTI_ClearITPendingBit(EXTI_Line1); NVIC_EnableIRQ(EXTI1_IRQn); /**< Wait till DMA transmission is ready */ while ((DMA2_Stream1->CR & DMA_SxCR_EN) || (WaitingRxUART == true)); /**< Stop edge interrupt */ NVIC_DisableIRQ(EXTI1_IRQn); DMA_Cmd(DMA2_Stream1, DISABLE); /**< Decode data from DMA buffer */ /**< We are processing 8 data bits, don't know yet why it should be started with Buff[2]? */ for (i = 2; i < 10; i++) { val >>= 1; if ((Buff[i] & (1 << 1)) == 0) val |= 0x80; } При комутации приемопередатчика возникает короткий импульс, который нужно фильтровать, это происходит в прерывании: /**< External interrupt for detecting rising edge of UART packet */ void EXTI1_IRQHandler(void) { if (EXTI_GetITStatus(EXTI_Line1) != RESET) { /**< Clear the UART EXTI line pending bit */ EXTI_ClearITPendingBit(EXTI_Line1); /**< Wait 1 us and check input */ TIM10->CNT = 0; TIM10->SR = 0; while ((TIM10->SR & TIM_IT_Update) == 0); if ((GPIOA->IDR & (1 << 1)) == 0) return; /**< Real start bit received, no spike */ /**< Stop edge interrupt */ NVIC_DisableIRQ(EXTI1_IRQn); WaitingRxUART = false; /**< Start DMA GPIO capture */ /**< Receive 10 bits (8 data bits * 2 stop bits) */ TIM8->CR1 &= ~TIM_CR1_CEN; TIM_SetCounter(TIM8, TIM8->ARR / 2); TIM_ClearITPendingBit(TIM8, TIM_IT_Update); TIM8->CR1 |= TIM_CR1_CEN; DMA_SetCurrDataCounter(DMA2_Stream1, 10); DMA_Cmd(DMA2_Stream1, ENABLE); } } Все вроде бы хорошо работает, прием идет, выбросы отфильтровываются, но есть одно но - периодически, причем достаточно часто, происходит сбой, вместо, к примеру 0xAA принимается 0xAB, я посмотрел, что оказывается в буфере, куда собираются значения IDR, и обнаружил там наряду с нормальными значениями состояния входов GPIO пару нулевых значений, причем они идут не первыми и не последними, то есть, буффер выглядит так: 0x9B6C, 0x00, 0x00, 0x9B6C, 0x9B6E, ... Такого не может быть, потому что просто не может быть. Такое впечатление, что канал DMA с чем-то коллидирует и пишет в буфер нули. Может быть, кто-то сталкивался с подобным? Буду рад услышать какие-то советы, потому что голова уже сломалась. На осциллографе данные выглядят нормально (за исключением выбросов), но они точно фильтруются.
  17. Не удивлюсь. Потому и сваливают все в производство, если не удалось поймать хороший грант. Но прикольно, конечно, осознавать эти цифры на фоне всех нынешних разговоров про инвестиции в образование, дигитализацию и прочее. Видимо, очередные проекты по распилу на очереди, деньги инвестируются не в кадры, а в то, что можно расписать с друзьями. Я думаю, Вы не на этом сайте оформлять сотрудника будете, а в BAMF
  18. Сайт BAMF подойдет? http://www.bamf.de/DE/Migration/Arbeiten/BuergerDrittstaat/BlaueKarte/blaue-karte-node.html
  19. Не думаю, что кто-то смог обогнать в этом деле Германию или Швецию.
  20. Даже за 40 тысяч по нынешним временам разве что студента можно нанять, только что из института. И то только до того момента, пока он что-то другое себе не найдет. А уж в разделе Embedded Linux и Qt вообще нереально. Это я уже молчу про то, что за такие деньги невозможно оформить Blaue Karte, нужно минимум 42 тысячи по текущим требованиям. Ну и вообще, на такие деньги никому из России не советовал бы переезжать, помимо проблем с языком, ксенофобии, отсутствия перспектив карьерного роста, с такой зарплатой и местными ценами почти на все это реально грозит выживанием и сведением концов с концами, разве что одному как-то худо-бедно. Такие предложения интересны разве что одиноким жителям глубинки. Да, так и есть, если зарплата меньше 2000 в месяц, то особого смысла работать, в принципе, и нет. Государство пожирает само себя, устанавливая такие правила, поощряющие тунеядство и экономическую миграцию с единственной целью интеграции в социальную систему. Уже 41800 с 2019 года, так что даже с максимально предложенной автором ставкой и слезными письмами не прокатит.
  21. Тоже интересно послушать. Одно дело - писать ассемблерные вставки для ускорения тонких мест, а другое - бизнес-логику на 8000 строк. Могу себе представить отличия в скорости разработки.
  22. Нет, мне загрузчик не нужен. Проблема в скриптах для j-link, которые идут в комплекте с EmBitz, что конкретно - я до сих пор понять не могу.
×
×
  • Создать...