jcxz 0 Posted November 13, 2020 · Report post 2 часа назад, evgen2 сказал: про ноги и про возможность сгенерировать одной ногой одно прерывание с двумя взаимноисключающими флагами - не пишут В смысле? Если Вы разрешили прерывания и по фронту и по спаду, то вроде бы очевидно, что будут регистрироваться и те и другие. Вы ожидали чего-то другого? 13 часов назад, AlexandrY сказал: А так есть известная бага связанная с медлительностью периферии портов по отношению к ядру у Сortex-ов Помогает __DSB(); на выходе из прерывания. Если писать ISR с умом и сбрасывать флаг запроса прерывания в периферии в начале ISR, а не в самом его конце, то как правило никакие DSB не нужны. По-крайней мере у меня в куче проектов на разных МК на Cortex-M нет ни одной DSB поставленной с этой целью. И тем не менее - всё прекрасно работает. Да: иногда для корректного сброса какого-то флага в регистрах периферии, необходимо после записи в регистр (сбрасывающего значения) затем ещё и прочитать обратно этот регистр. Но что характерно - такое я встречал часто в периферии STM32. И причём это никак не оговаривалось в документации. Встречал такую необходимость и в некоторых регистрах периферии других МК других производителей, но там (в таких случаях) это явно указано в мануале (где это нужно). Но DSB к этому случаю тоже никаким боком не относится, так как если заменить обратное чтение такого регистра командой DSB, то работа нарушается. Проверено неоднократно на разных регистрах STM32F4. Quote Ответить с цитированием Share this post Link to post Share on other sites
Arlleex 0 Posted November 13, 2020 · Report post 1 час назад, evgen2 сказал: про возможность сгенерировать одной ногой одно прерывание с двумя взаимноисключающими флагами - не пишут Пишут про механизм активизации прерывания и постановку прерывания в ожидание. Вам уже правильно сказали - естественно, периферия не формирует флаги одновременно. Может быть несколько различных ситуаций, при котором можно будет наблюдать такое поведение. С концевика, понятное дело, может идти "гармошка" от дребезга контактов. Причем импульсы абсолютно разной ширины. И, например, может получиться ситуация, когда период импульса меньше времени распространения сигнала от периферии в NVIC. Но сами по себе фронты вполне различимы входными схемами синхронизации на GPIO. Будет сформировано 1 прерывание, а на GPIO будет установлено оба флага. Другая ситуация, когда, например, находясь в высокоприоритетном прерывании от какой-то другой периферии, пришел импульс на GPIO. Будет такой же результат. А может NVIC засекает и оба прерывания, но в момент обработки первого прерывания он видит и флаг второго на периферии. В этом случае статус прерывания по GPIO на NVIC будет "активно и ожидает обработки". Можно сделать проверку на входе в прерывание перед очисткой флага. А еще это зависит много от чего - например, как реализована конкретная линия запроса прерывания в NVIC - по импульсу или по уровню и т.д. Quote Ответить с цитированием Share this post Link to post Share on other sites
evgen2 0 Posted November 13, 2020 · Report post 1 hour ago, haker_fox said: Что готовое? Набросайте эскиз, как подключен датчик к ножке МК. Не забудьте указать длину кабеля, наличие экранов, как выполняется преобразование уровней. готовая плата с разведенными ногами, клеммами и разъемами, в идеале с показометром и передатчиком в вышестоящую систему. Quote Насколько я знаю, периферия может выставлять флаги, даже если прерывания не разрешены. Иначе бы поллинг флагов никогда не был бы возможен.User Manual на STM32F091. В любом случае одновременное выставление двух противоположных флагов несколько нетривиально. Во всяком случае для меня. Quote User Manual на STM32F091 хм, в LPX мануалах такие подробности не описаны. Если судить по описанию используется логическое сравнение битов с маской, можно конечно это назвать фильтрацией, но ИМХО это будет натяжкой Quote Вы же сказали, что у вас конвейер, а это и искрящие двигатели/контакторы, помехи в сеть и т.п. ну да. Только проблема в том, что когда все это гудит и крутится - с осциллографом не подлезть, а когда остановлено, то и этих двойных прерываний не приходит. В лабораторных условиях другое питание, земля и вообще все замечательно, а в боевых "получается как всегда". Quote Ответить с цитированием Share this post Link to post Share on other sites
jcxz 0 Posted November 13, 2020 · Report post 27 минут назад, Arlleex сказал: Вполне естественный результат взаимодействия доменов с различными частотами и шинной инфраструктурой. Я как правило, если в коде нужно произвести запись в регистры периферии, находящейся на разных шинах (доменах тактирования), при условии что эта периферия как-то взаимодействует между собой, использую команду DMB. Например: Если нужно включить тактирование какого-то блока, а потом сконфигурить его регистры, то включаю тактирование, DMB, пишу в регистры. Или: инит DMA для обслуживания какой-то периферии, DMB, инит регистров периферии. Ну или если есть возможность, то вместо DMB в данном случае можно использовать обратное чтение регистров, которые писал первыми. Quote Ответить с цитированием Share this post Link to post Share on other sites
Arlleex 0 Posted November 13, 2020 · Report post 3 минуты назад, jcxz сказал: Я как правило, если в коде нужно произвести запись в регистры периферии... Аналогично поступаю. Правда DSB использую. В некоторых исходниках вовсе видел последовательность DMB/DSB. Честно говоря, ARM отдает реализацию интерфейса периферийной шины на откуп производителю МК, а тот в свою очередь неохотно пишет об особенностях. В том числе, на какие регионы памяти периферии (атрибут Device, вроде как, согласно спецификации) распространяется буфер записи. И есть ли он вообще. Quote Ответить с цитированием Share this post Link to post Share on other sites
evgen2 0 Posted November 13, 2020 · Report post 25 minutes ago, jcxz said: В смысле? Если Вы разрешили прерывания и по фронту и по спаду, то вроде бы очевидно, что будут регистрироваться и те и другие. Вы ожидали чего-то другого? Я ж говорю - неочевидно для меня, бестолкового. И в примерах эта ситуация старательно обойдена. Во многих других случаях неочевидные вещи описаны и в мануале и в примерах Quote Ответить с цитированием Share this post Link to post Share on other sites
dimka76 0 Posted November 13, 2020 · Report post 10 minutes ago, jcxz said: Я как правило, если в коде нужно произвести запись в регистры периферии, находящейся на разных шинах (доменах тактирования), при условии что эта периферия как-то взаимодействует между собой, использую команду DMB. Например: Если нужно включить тактирование какого-то блока, а потом сконфигурить его регистры, то включаю тактирование, DMB, пишу в регистры. Или: инит DMA для обслуживания какой-то периферии, DMB, инит регистров периферии. Ну или если есть возможность, то вместо DMB в данном случае можно использовать обратное чтение регистров, которые писал первыми. 3 minutes ago, Arlleex said: Аналогично поступаю. Правда DSB использую. В некоторых исходниках вовсе видел последовательность DMB/DSB. Честно говоря, ARM отдает реализацию интерфейса периферийной шины на откуп производителю МК, а тот в свою очередь неохотно пишет об особенностях. В том числе, на какие регионы памяти периферии (атрибут Device, вроде как, согласно спецификации) распространяется буфер записи. И есть ли он вообще. Можно фрагмент кода в качестве примера ? Quote Ответить с цитированием Share this post Link to post Share on other sites
Arlleex 0 Posted November 13, 2020 · Report post 7 минут назад, dimka76 сказал: Можно фрагмент кода в качестве примера ? void can_Init(void) { rb_Init(&CANRxQ); EnCANClk(CAN_CAN_NUM); __DMB(); __DSB(); PCAN->MCR = B16 | CAN_MCR_INRQ; while(~PCAN->MSR & CAN_MSR_INAK); PCAN->MCR |= CAN_MCR_ABOM | CAN_MCR_RFLM | CAN_MCR_TXFP; #define DIV 9 #define BS1 13 #define BS2 2 #define SJW 1 PCAN->BTR = (SJW - 1) << 24 | (BS2 - 1) << 20 | (BS1 - 1) << 16 | (DIV - 1); #undef DIV #undef BS1 #undef BS2 #undef SJW PCAN->IER = CAN_IER_FMPIE0; NVIC_EnableIRQ(CANRX0IRQ); NVIC_SetPriority(CANRX0IRQ, 2); InitFilters(); EnGPIOClk(CAN_GPIO_RX); EnGPIOClk(CAN_GPIO_TX); __DMB(); __DSB(); DefPinInPDis(CAN_GPIO_RX); DefPinAltPP(CAN_GPIO_TX); PCAN->MCR &= ~CAN_MCR_INRQ; while(PCAN->MSR & CAN_MSR_INAK); } Однако, бывает, что мануал просит выдержать какое-то количество тактов после включения периферии. Тут DMB/DSB не помогут. Quote Ответить с цитированием Share this post Link to post Share on other sites
VladislavS 0 Posted November 13, 2020 · Report post 36 минут назад, Arlleex сказал: Тут DMB/DSB не помогут. Нужны не DMB/DSB, а тупо любая задержка. Quote Ответить с цитированием Share this post Link to post Share on other sites
Arlleex 0 Posted November 13, 2020 · Report post 3 минуты назад, VladislavS сказал: Нужны не DMB/DSB, а тупо любая задержка. Может и так. Но в случае, если в RM нет требований по тактам, то вполне можно опираться на аппаратные средства AMBA. А конкретно - использовать инструкции барьеров. Они сами знают, сколько тактов требуется для гарантированной записи. Quote Ответить с цитированием Share this post Link to post Share on other sites
Сергей Борщ 0 Posted November 13, 2020 · Report post 1 час назад, evgen2 сказал: хм, в LPX мануалах такие подробности не описаны. Там просто сказано, что их УАПП - клон 16С550. Подробности ищите в документации на оригинал. Quote Ответить с цитированием Share this post Link to post Share on other sites
jcxz 0 Posted November 13, 2020 · Report post 1 час назад, dimka76 сказал: Можно фрагмент кода в качестве примера ? Фрагмента рестарта АЦП->DMA (АЦП тактируется от нескольких таймеров): fdmaU->CHEN = (1 << (nDMALINE_adc_fast & 7)) * 0x100; //выключить fastADC DMA ... fdmaC->DAR = (u32)adcFastData[i1]; fdmaC->SAR = (u32)&VADC.G[0].RES[8]; fdmaC->CTL[1] = ncell(adcFastData[0][0].raw); __DMB(); AtomicOr(&DLR.LNEN, 1 << nDMALINE_adc_fast); //Включить DLR линию, сбрасывая ожидающий запрос __DMB(); fdmaU->CHEN = (1 << (nDMALINE_adc_fast & 7)) * 0x101; //Включить fastADC DMA __DMB(); VADC.G[3].VFR = VADC.G[2].VFR = VADC.G[1].VFR = VADC.G[0].VFR = B16 - 1; __DMB(); CCU_ADCF_S.TCSET = B0; //start the fastADC timer ... Здесь идут операции с IO-регистрами в последовательности: DMA, DLR (DMA Line Router), DMA, АЦП, таймер. Все эти периферийные блоки связаны между собой взаимодействиями (сигналами). Quote Ответить с цитированием Share this post Link to post Share on other sites
dimka76 0 Posted November 13, 2020 · Report post 54 minutes ago, Arlleex said: Spoiler void can_Init(void) { rb_Init(&CANRxQ); EnCANClk(CAN_CAN_NUM); __DMB(); __DSB(); PCAN->MCR = B16 | CAN_MCR_INRQ; while(~PCAN->MSR & CAN_MSR_INAK); PCAN->MCR |= CAN_MCR_ABOM | CAN_MCR_RFLM | CAN_MCR_TXFP; #define DIV 9 #define BS1 13 #define BS2 2 #define SJW 1 PCAN->BTR = (SJW - 1) << 24 | (BS2 - 1) << 20 | (BS1 - 1) << 16 | (DIV - 1); #undef DIV #undef BS1 #undef BS2 #undef SJW PCAN->IER = CAN_IER_FMPIE0; NVIC_EnableIRQ(CANRX0IRQ); NVIC_SetPriority(CANRX0IRQ, 2); InitFilters(); EnGPIOClk(CAN_GPIO_RX); EnGPIOClk(CAN_GPIO_TX); __DMB(); __DSB(); DefPinInPDis(CAN_GPIO_RX); DefPinAltPP(CAN_GPIO_TX); PCAN->MCR &= ~CAN_MCR_INRQ; while(PCAN->MSR & CAN_MSR_INAK); } Однако, бывает, что мануал просит выдержать какое-то количество тактов после включения периферии. Тут DMB/DSB не помогут. 8 minutes ago, jcxz said: Фрагмента рестарта АЦП->DMA: Spoiler ... fdmaC->DAR = (u32)adcFastData[i1]; fdmaC->SAR = (u32)&VADC.G[0].RES[8]; fdmaC->CTL[1] = ncell(adcFastData[0][0].raw); __DMB(); AtomicOr(&DLR.LNEN, 1 << nDMALINE_adc_fast); //Включить DLR линию, сбрасывая ожидающий запрос __DMB(); fdmaU->CHEN = (1 << (nDMALINE_adc_fast & 7)) * 0x101; //Включить fastADC DMA __DMB(); VADC.G[3].VFR = VADC.G[2].VFR = VADC.G[1].VFR = VADC.G[0].VFR = B16 - 1; __DMB(); CCU_ADCF_S.TCSET = B0; //start the fastADC timer ... Здесь идут операции с IO-регистрами в последовательности: DMA, DLR (DMA Line Router), DMA, АЦП, таймер. Все эти периферийные блоки связаны между собой взаимодействиями (сигналами). Спасибо ! Quote Ответить с цитированием Share this post Link to post Share on other sites
haker_fox 0 Posted November 13, 2020 · Report post 2 hours ago, jcxz said: Да: иногда для корректного сброса какого-то флага в регистрах периферии, необходимо после записи в регистр (сбрасывающего значения) затем ещё и прочитать обратно этот регистр. А вы это опытным путём установили? Просто интересно, я бы не догадался до такого) 2 hours ago, evgen2 said: В лабораторных условиях другое питание, Я уже говорил ни один раз - ЭМС. Или вы недооцениваете такие проверки? Неужели вы вообще не испытываете своё устройство на промышленные помехи??? Я вам уже подсказали и другой путь - генератор произвольных сигналов. Без такого рода испытаний - ваш прибор фикция. И место ему на свалке. Если вы такие испытания провели, то почему-то молчите об этом. При этом уже битых три страницы идут какие-то удивления о работе периферии, о методах фильтрации и ничего больше по делу. Как будто бы это нам, а не вам надо. Quote Ответить с цитированием Share this post Link to post Share on other sites
jcxz 0 Posted November 13, 2020 · Report post 12 минут назад, haker_fox сказал: А вы это опытным путём установили? Просто интересно, я бы не догадался до такого) Примерно так. Сначала как во всех других МК поставил DMB, то потом обнаружил, что при полной оптимизации и выполнении из флешь с включённым кешем оно стало иногда сбоить (непериодически, но так как я только что сделал такие модификации кода, то сразу заметил связь). (При полной оптимизации и выполнении из ОЗУ, или выполнении из флешь, но с выключенным кешем 0 всё ок - год так работало без сбоев). Quote Ответить с цитированием Share this post Link to post Share on other sites