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

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


Рекомендуемые сообщения

Привет, знатоки. Написал свою первую программу для контроллера 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(с копейками)мс. В принципе в теле цикла может быть что угодно, кроме пустоты, и тайминг налаживается.

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

Спасибо.

 

 

 

 

Изменено пользователем n_angelo
Ссылка на комментарий
Поделиться на другие сайты

21.09.2019 в 20:10, n_angelo сказал:

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

5 часов назад, ruhi сказал:

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. 

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

32 minutes ago, ruhi said:

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

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

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

 

Изменено пользователем n_angelo
Ссылка на комментарий
Поделиться на другие сайты

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

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

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

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

Я так думаю.

Ссылка на комментарий
Поделиться на другие сайты

20 минут назад, n_angelo сказал:

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

18 минут назад, Yurkin2015 сказал:

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

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

Я так думаю.

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

Ссылка на комментарий
Поделиться на другие сайты

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

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

 

3 minutes ago, n_angelo said:

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

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

Ссылка на комментарий
Поделиться на другие сайты

23 минуты назад, n_angelo сказал:

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

  • 1 месяц спустя...

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

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы публикуете как гость. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...