Jump to content
n_angelo

STM8L. Пустой бесконечный цикл тормозит тайминг.

Recommended Posts

Привет, знатоки. Написал свою первую программу для контроллера STM8L152C6T6 (STM8L-Discovery). Это, собственно, моя первая программа для контроллеров вообще. Я многого не знаю и не понимаю. Возможно ваш ответ на мой вопрос будет банален.

Используемая периферия: DAC, DMA, TIM4, CLK, GPIO

Задача у программы такая:

В EEPROM зашит один период синусоиды с дискретизацией 44100Гц. Период занимает ровно 101 байт, что по сути должно быть равно 2,29мс (1/44100*101). В коде программы только конфигурация периферии, одно прерывание на кнопке и пустой бесконечный цикл, который ничего не делает. Всю работу выполняет таймер, который настроен выдавать запрос к DMA на каждые 1/44100 (ядро тактируется 2мГц, таймер считает до 45). В свою очередь DMA забирает из EEPROM по одному байту на каждый запрос от таймера и передаёт его в DAC. Далее DAC выводит бесконечную синусоиду на ногу PF0. Прерывание на кнопке запускает весь этот механизм и зажигает светодиод.

Проблема:

Измеряя ногу PF0 осциллографом было замечено, что период синусоиды занимает около ≈4мс. Фото под катом.

Скрытый текст

DSC_0008.JPG.d3bf50618d847e1e21b7cf30ee1b20d8.JPG

Меня это расстроило. Экспериментально выяснилось, что стоит только вписать в бесконечный цикл какую-нибудь проверку, например, [если значение текущего байта синусоиды = 0xFF, то зажечь светодиод, если 0x00, то потушить], то осциллограф показывает правильный тайминг в 2(с копейками)мс. В принципе в теле цикла может быть что угодно, кроме пустоты, и тайминг налаживается.

Я не могу отдебажить дизассемблер, т.к. его не знаю. Это у меня в планах. Но я очень хочу понять, что происходит и почему пустой цикл рушит тайминг.

Спасибо.

 

 

 

 

Edited by n_angelo

Share this post


Link to post
Share on other sites
21.09.2019 в 20:10, n_angelo сказал:

что происходит и почему пустой цикл рушит тайминг

вот если ты нам расскажешь, будет очень интересно. Я бы померил, например, сколько времени занимает от входа в прерыванием до установки значения в ДАКе.


Можно сделать все! Но чем больше можно, тем больше нельзя!

Share this post


Link to post
Share on other sites
5 часов назад, ruhi сказал:

вот если ты нам расскажешь, будет очень интересно. Я бы померил, например, сколько времени занимает от входа в прерыванием до установки значения в ДАКе.

К сожалению, мой осциллограф одноканальный и показывает только то, что произошло от момента триггера. А график в дебаггере показывает, что один семпл (1/44100) выводится раз в 5 секунд.

Других способов измерить я пока не придумал.

99426537_2019-09-2319_46_02.png.fe57fbaaef3751de8f53225210fa437c.png

Share this post


Link to post
Share on other sites

Вебинар «МЭМС-датчики ST для работы со звуком – новые возможности» (28.10.2020)

28 октября все желающие приглашаются для участия в вебинаре, посвященном семейству МЭМС-датчиков STMicroelectronics для акустических приложений. Предметом детального рассмотрения на вебинаре станут микрофоны, их топологии применения и возможности. Вы услышите о новых мультирежимных широкодиапазонных микрофонах с нижним портом и PDM-интерфейсом для систем с батарейным питанием.

Подробнее

19 часов назад, n_angelo сказал:

то, что произошло от момента триггера.

В коде в начале функции прерывания надо поставить инструкцию переключения уровня на любую доступную ногу процессора, перед инструкцией записи в ДАК тоже поставить переключение ноги (той же или другой - как тебе удобней) и посмотри осциллографом сигнал на этой ноге (ногах). Это вряд ли даст объяснение проблеме, но возможно наведет тебя на мысли в какую стороны копать, что еще посмотреть!


Можно сделать все! Но чем больше можно, тем больше нельзя!

Share this post


Link to post
Share on other sites

STM32L562E-DK – первая отладочная платформа ST на ядре ARM Cortex-M33

STMicroelectronics представляет демонстрационно-отладочную платформу на базе ядра Cortex-M33 – STM32L562E-DK. Данная платформа основана на микроконтроллере нового семейства – STM32L5. STM32L562E-DK позволяет разработчику в полной мере раскрыть и опробовать новые возможности микроконтроллеров STM32L5 с тщательно проработанным функционалом для обеспечения высокого уровня безопасности и защиты.

Подробнее

32 minutes ago, ruhi said:

в начале функции прерывания

Там нет никакого прерывания, вся работа по переносу байтов происходит по DMA в фоновом режиме без участия программы. То есть процессор непрерывно крутит пустой цикл, а таймер сам по себе тикает и с каждым тиком заставляет DMA читать память и записывать в ЦАП.

On 9/21/2019 at 6:10 PM, n_angelo said:

почему пустой цикл рушит тайминг.

Без Вашего кода в студии трудно что-либо сказать.

Share this post


Link to post
Share on other sites

Тест уровня кондуктивной помехи электронного устройства

Электромагнитная совместимость (ЭМС) является важным параметром электронных устройств, особенно это актуально в современном мире, насыщенном разнообразными гаджетами. Специалисты компании Mornsun подготовили видеоролик по тестированию одной из составляющих ЭМС – кондуктивной помехи.

Подробнее

3 часа назад, ruhi сказал:

В коде в начале функции прерывания надо поставить инструкцию переключения уровня на любую доступную ногу процессора, перед инструкцией записи в ДАК тоже поставить переключение ноги (той же или другой - как тебе удобней) и посмотри осциллографом сигнал на этой ноге (ногах). Это вряд ли даст объяснение проблеме, но возможно наведет тебя на мысли в какую стороны копать, что еще посмотреть!

Намёк понял. Буду думать.

Share this post


Link to post
Share on other sites
3 часа назад, Yurkin2015 сказал:

Там нет никакого прерывания, вся работа по переносу байтов происходит по DMA в фоновом режиме без участия программы. То есть процессор непрерывно крутит пустой цикл, а таймер сам по себе тикает и с каждым тиком заставляет DMA читать память и записывать в ЦАП.

Без Вашего кода в студии трудно что-либо сказать.

Наверное он имел ввиду самое первое прерывание, которое включает таймер.

Прилагаю код. Осциллограф выдаёт полный период за ≈4мс, хотя должен за ≈2,29мс.

main.c

Скрытый текст

#include "main.h"

#pragma vector=EXTI1_vector 
__interrupt void btnInterrupt(void) 
{
  PE_ODR |= (1<<LED); // led on
  TIM4_CR1 |= TIM4_CR1_CEN;
  EXTI_SR1 |= (0x02); //reset flag on handler exit
}

int main( void )
{
  // LED init
  PE_DDR |= (1<<LED);
  PE_CR1 |= (1<<LED);
  
  // BUTTON init
  PC_DDR &= ~(1<<BUTTON);
  PC_CR1 |= (1<<BUTTON);
  PC_CR2 |= (1<<BUTTON);
  
  // CLK init
  CLK_PCKENR1 |= CLK_TIM4;
  CLK_PCKENR1 |= CLK_DAC;
  CLK_PCKENR2 |= CLK_DMA1;
  
  // TIM4 init
  TIM4_ARR = TIM4_ARR_44100HZ;
  TIM4_DER |= TIM4_DER_EN;
  
  // DMA init
  DMA1_GCSR |= DMA1_GCSR_GEN;
  DMA1_C3CR |= DMA1_C3CR_MINCDEC;
  DMA1_C3CR |= DMA1_C3CR_CIRC;
  DMA1_C3CR |= DMA1_C3CR_DIR;
  DMA1_C3CR |= DMA1_C3CR_TCIE;
  DMA1_C3NDTR = 101;
  DMA1_C3M0ARH = 0x10; //0x1000 (10 - HBS)
  DMA1_C3M0ARL = 0x00; //0x1000 (00 - LBS)
  DMA1_C3PARH_C3M1ARH = 0x53; //0x5390 (53 - HBS)
  DMA1_C3PARH_C3M1ARL = 0x90; //0x5390 (90 - LBS)
  DMA1_C3CR |= DMA1_C3CR_EN;
  
  // DAC init
  DAC_CH1CR1 |= DAC_CH1CR1_EN;
  
  // interrupt init
  EXTI_CR1 |= (1<<BUTTON);
  asm("RIM");
  
  while(1)
  { 
  }
  
}

 

 

main.h

Скрытый текст

#define PC_IDR          *(unsigned char*)0x00500B
#define PC_DDR          *(unsigned char*)0x00500C
#define PC_CR1          *(unsigned char*)0x00500D
#define PC_CR2          *(unsigned char*)0x00500E
#define PE_ODR          *(unsigned char*)0x005014
#define PE_DDR          *(unsigned char*)0x005016
#define PE_CR1          *(unsigned char*)0x005017

#define CLK_PCKENR1     *(unsigned char*)0x0050C3
#define CLK_PCKENR2     *(unsigned char*)0x0050C4
#define CLK_TIM4        0x4
#define CLK_DAC         0x80
#define CLK_DMA1        0x10

#define TIM4_CR1        *(unsigned char*)0x0052E0
#define TIM4_ARR        *(unsigned char*)0x0052E9
#define TIM4_DER        *(unsigned char*)0x0052E3
#define TIM4_CR1_CEN    0x1
#define TIM4_ARR_44100HZ        0x2D
#define TIM4_DER_EN     0x1

#define DMA1_GCSR       *(unsigned char*)0x005070
#define DMA1_C3CR       *(unsigned char*)0x005093
#define DMA1_C3SPR      *(unsigned char*)0x005094
#define DMA1_C3NDTR     *(unsigned char*)0x005095
#define DMA1_C3M0ARH    *(unsigned char*)0x005099
#define DMA1_C3M0ARL    *(unsigned char*)0x00509A
#define DMA1_C3PARH_C3M1ARH    *(unsigned char*)0x005096
#define DMA1_C3PARH_C3M1ARL    *(unsigned char*)0x005097
#define DMA1_C3CR_MINCDEC       0x20    
#define DMA1_C3CR_CIRC          0x10
#define DMA1_C3CR_DIR           0x08
#define DMA1_C3CR_TCIE          0x02
#define DMA1_C3CR_EN            0x01
#define DMA1_GCSR_GEN           0x01

#define DAC_CH1CR1     *(unsigned char*)0x005380
#define DAC_DHR8       *(unsigned char*)0x005390 
#define DAC_CH1CR1_EN   0x01

#define EXTI_CR1        *(unsigned char*)0x0050A0
#define EXTI_SR1        *(unsigned char*)0x0050A3
#define EXTI1_vector    11

#define P0 0
#define P1 1
#define P2 2
#define P3 3
#define P4 4
#define P5 5
#define P6 6
#define P7 7
#define LED P7
#define BUTTON P1

 

Edited by n_angelo

Share this post


Link to post
Share on other sites
On 9/21/2019 at 6:10 PM, n_angelo said:

почему пустой цикл рушит тайминг.

Думается, дело в том, что DMA и ядро процессора используют одну и ту же системную шину для доступа к памяти и периферии. Когда имеем пустой цикл, то ядро ни хрена не делает, а только непрерывно занимает шину для бесконечных прыжков по памяти программ по кругу. Если заставить ядро что-нибудь делать внутри себя со своими регистрами, типа прибавлять единичку к регистру, то шина будет освобождаться на время, и в этот момент DMA будет пропихивать свои байты по свободной шине.

Ну, или установить приоритет DMA над ядром, чтобы шина освобождалась по первому же требованию DMA.

Я так думаю.

Share this post


Link to post
Share on other sites
20 минут назад, n_angelo сказал:

Наверное он имел ввиду самое первое прерывание, которое включает таймер.

Нет, я это действительно упустил, но значит надо включить прерывания таймера и поверить его период этим методом.


Можно сделать все! Но чем больше можно, тем больше нельзя!

Share this post


Link to post
Share on other sites
18 минут назад, Yurkin2015 сказал:

Думается, дело в том, что DMA и ядро процессора используют одну и ту же системную шину для доступа к памяти и периферии. Когда имеем пустой цикл, то ядро ни хрена не делает, а только непрерывно занимает шину для бесконечных прыжков по памяти программ по кругу. Если заставить ядро что-нибудь делать внутри себя со своими регистрами, типа прибавлять единичку к регистру, то шина будет освобождаться на время, и в этот момент DMA будет пропихивать свои байты по свободной шине.

Ну, или установить приоритет DMA над ядром, чтобы шина освобождалась по первому же требованию DMA.

Я так думаю.

Моя благодарность! Помогло. Установил приоритет над ядром. Теперь тайминг правильный. Насколько приоритет над ядром может замедлить саму программу? Я так понимаю здесь нужно самому выбирать, либо работа в реалтайм связки (TIM->DMA->DAC) и пустить в жертву работу программы, либо никакого реалтайма в этой связке, но зато код будет работать без задержек? Насколько RTOS помогает с этим справиться?

Share this post


Link to post
Share on other sites
On 9/21/2019 at 6:10 PM, n_angelo said:

таймер считает до 45

 

3 minutes ago, n_angelo said:

может замедлить саму программу?

Ну, вот, пока таймер считает, DMA шину не трогает. То есть 1 раз из 45 тактов ядро будет подторможено, замедление составит в худшем случае 1/45, около 2%.

Share this post


Link to post
Share on other sites
1 минуту назад, Yurkin2015 сказал:

1 раз из 45 тактов ядро будет подторможено

Да, логично) Еще раз спасибо.

Share this post


Link to post
Share on other sites
23 минуты назад, n_angelo сказал:

Помогло. Установил приоритет над ядром.

Интересно! Оно же должно задерживать вывод КАЖДОГО значения в ДАК , почему же период целого синуса (правильно понимаю?) то меняется. У меня первая мысль была про это, но оно вроде на интегральный период синуса не должно влиять, джитер в периоде вывода самплов должен наблюдаться, - интересно! Хотя другого объяснения и нет!


Можно сделать все! Но чем больше можно, тем больше нельзя!

Share this post


Link to post
Share on other sites

спасибо, интересное замечание. надо бы конечно собранный код посмотреть, что сгенерировал компилятор на пустой цикл... если он не пустой - работает нормально, а если пустой, то такая задержка на "аппаратные", не программные передачи данных между модулями микроконтроллера (в данном случае память->DAC)

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Сообщения

    • Узч начинается с питания, любой хороший схемотехнически и на достойных деталях "ляжет" от плохого питания (во всем диапазоне, по звуку, хоть и Кг будет ультралинейный). Частота Шумена это научный факт, нищета это в голове и элементарно программируется и управляется (ДОТУ, труд морской разведки). Бафи, я уже в телефончике, баю бай, не ходите к алибабай, покупайте для себя вишай.
    • Потеря обоняния,  запахов, температура и прочее. Это не говорит что тут виноват какой-то вирус, или корона выдуманная. Ты этот вирус видел в микроскоп?
    • наличие скола это хоршо... значит диодная диагональ размагничивает... теперь надо, контролируя  сигнал с тт плавно увеличивать питанье моста и засечь момент насыщенья сердешного... это и будет максимальное питанье моста... синусоподобное возбужденье? это значит диоды закрылись и остаток энергетики резонирует Lm1C1... а в чём нерасчетность первички? тут ключевое - отсутствие зазорра... дальше можно не считать... уже... и вторичку не мотать...
    • жесть))) это больше похоже на еще одну псевдонауку - вуду или проповеди очередного кашпировскго) агресия и зависть - это от нищеты=безнадежности - и безграмотности - по другому - дурости)) в сетях кучи когнетивных искажений. идеальная полка - иип для умзч - порой это еще плюс помехи ) - связанные с жесткой работой трансформатора , потому идеальный вариант для него - это резонанс - самому бы его еще освоить)) а так смотря для чего - ес недорогой класс умзч - можно не заморачиватся.имхо
    • новый блок без Can, есть только один провод speed info. вход датчика спидометра находится в блоке центральной электроники. Обвединённый 4 и 5 провод это цифровая шина Can, по которой блоки общаются между собой, к ним датчик нельзя подключать. Если без АБС, то к блоку центральной электроники(1 схема). Если с АБС, то все датчики к блоку АБС(2схема). Спидометр в приборной панели получает информацию по CAN шине либо от блока АБС, либо от блока Центральной электроники.
    • офтоп (чтоб не забанели) Частота Шумена это измерение частоты Земли, ну, влияет она на человека... низкочастотные впадают в зависть и распирает их зло, ты сам это наблюдаешь, агрессия растет каждый год, всё сильнее и сильнее (у низкочастотных). по теме, вишай ещё есть в платане, я только на них собирал DC/DC (автозвук) - идеальные прямоугольники, идеальная полка (не хуже топ хеликс). Собирал первый раз, 4 бп и все четыре без танца, мотал бублик правда 4 раза, под подсказками Эдуарда Марилова.

  • Клеммные колодки, 2 pin, 10 шт.

  • Similar Content

    • By kostake
      Продам ЦАП, на PCM5102, авторский. Выхлоп германиевый. Вход I2S.
      В роли транспорта подключен-Up2Stream Pro . Поддержка wifi ,bluetooth,ethernet,USB,Airplay, DLNA, UPnP. Может играть напрямую с флешки. 
      Цена : 11тыс руб. Отправка без проблем, за счет покупателя. 
    • By n_angelo
      По приходящему на ножку A1 импульсу настроено прерывание. Прерывание должно отработать один раз и должно делать следующее: пауза 7 секунд, потом на 1,5 секунды открыть реле. Во время прерывания светодиод на плате гаснет и загорается в такт секундам. Код отрабатывает верно за исключением того, что прерывание отрабатывает 2 раза. Т.е. подали импульс, заморгал светодиод в течении 7ми секунд, потом щёлкнуло реле (открылось), затем опять щёлкнуло (закрылось), потом всё повторяется еще раз (7+1,5). В режиме дебага работает нормально. Пробовал отключать реагирование на прерывания во время его отработки:
      disableInterruupts(); ... enableInterruupts(); но не помогает.
      STM8S103F3P6
      Код прерывания
      Код в main.c
       
    • Guest User1324
      By Guest User1324
      Здравствуйте, помогите подключить USB-флешку к STM32F103RCT6, нужна дополнить принципиальную схему. Если есть возможность нарисовать.
    • By tishkanexx
      Продаю корпус для ЦАП (DAC) AK4490 / усилителя для наушников. Саму плату, если её нет, то можно купить на али ($36), фото платы прикладываю, могу дать ссылку на покупку.
      Корпус заказывал с завода breeze audio, минимально можно было заказать 2 корпуса ($30 два корпуса с доставкой), поэтому один продаю. Отдаю за $15, без наценки как есть. Если брать плату ЦАП-а и корпус, то получается $51, что дешевле, чем брать готовый ЦАП на том же ali за $60. Об этом писал здесь:
      На корпусе надпись: AKMDAC - HEADPHONE AMP (сделана по заказу вместо надписи breeze audio)
      Комплект: 4 силиконовые ножки, саморез для крепления "тюльпанов", 8 винтов для корпуса, сами части корпуса.
      Стоимость: 1000р или 15$. Пишите в лс.



    • By n_angelo
      Привет. Хочу узнать ваше мнение. Я новичок в embedded. Можно сказать, что пришел с веба. Малость Python, JS, C. Меня, конечно, предупреждали начать с AVR, но я уверенный в себе решил сразу залезть на STM32. Вынашивая идею для проекта, параллельно курив Reference Manual и Data Sheet по STM32, я понял что его будет слишком жирно для проекта. Я перескочил на STM8L. И тут меня начал огорчать мир embedded. При переходе между stm8 и stm32 нужно менять IDE (TrueStudio на STVD). Во избежание таких курьёзов я пересаживаюсь на IAR. В процессе подключения родной библиотеки от ST, понимаю что библиотека от IAR для того же самого STM8L152C6T6 дико отличается (макросы, структуры). Привет веб-разработка. Как такое могло произойти, что под один и тот же контроллер ST даёт одну библиотеку, а IAR другую. И нигде в уроках тебя не предупредят об этом. Ну, ребят, у меня всего одна жизнь. Вы уже договоритесь там между собой? Придите к единому стандарту. Или они так решили новичков завендерлочить? Моё мнение (не претендует на правильное): пробираясь сквозь тернии популярной архитектуры ARM, инфраструктуры, инструментария, забываешь про бизнес-логику устройств. А еще просто пропасть между "я ничего не понимаю" и "господи, я зажег светодиод". Речь не о копипастерах с уроков, а действительно понимая что ты делаешь, в каком регистре, что меняешь. Это путь в 2000 (а то и больше) страниц на английском перечитанных по несколько раз, чтобы отоложилось. И в конце тебя ждут разные версии одной и той же библиотки в разных IDE. И сидишь вдупляешь... ну почему... я же в правильный регистр кладу правильную маску... ох, наболело. Такое ощущение что не для людей это всё делали, не для людей.
      Ваше мнение?
×
×
  • Create New...