реклама на сайте
подробности

 
 
> Измерение Загрузки CPU, ARM7, lpc2367
whiteTigr
сообщение Aug 10 2011, 09:36
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 25-07-11
Пользователь №: 66 407



Захотел сделать измерение загрузки CPU.
Основная программа построена на прерываниях и работает с несколькими кнопками, сегментным индикатором и ком-портом.

Идея состоит в том, чтобы при начале любой (более-менее серъезной) процедуры стояло слово ImWorking, и заканчивалась процедура словом ImFinished.
Измеритель по этим словам выставляет тестовый диодик и считает сколько времени этот диодик простоял в высоком уровне (TimeInHighLevel).
Таймер в измерителе выдает прерывание раз в секунду, по которому значение TimeInHighLevel переписывается в буфер, доступный основной программе.

Вроде бы все получилось, но загрузка CPU, измеренная осцилографом, отличается от загрузки, измереной этим модулем.
Без оптимизации по осцилографу получается порядка 23% загрузки, модулем 24%. (вроде бы все нормально, списываем на погрешность)
С оптимизацией по времени выполнения получается: осцилограф - 13%, модуль 4%. (вот тут уже терзают сомнения)

И, так как я начинающий програмист, буду рад критике этого кода. sm.gif

Код
#include <LPC23xx.h>
#include "SystemMonitor.h"

// диодик
#define Work (1 << 1) // @ 1

#define PCTIM3  0x00800000; // 23

#define PCLK_TIMER3_OFFSET 14 // @ 1

#define INTTIM3 (1 << 27)

void Work_SET() { IOSET1 = Work; }
void Work_CLR() { IOCLR1 = Work; }

short WorkRefs = 0;

unsigned short CPUUsage = 0;

int TimeInHighLevel = 0;
int TimeSetHighLevel = 0;

__irq void Timer3Handler()
{
  if (WorkRefs > 0)  
    TimeInHighLevel += 10000 - TimeSetHighLevel;  

  CPUUsage = TimeInHighLevel;
  TimeInHighLevel = 0;
  TimeSetHighLevel = 0;

  T3IR = 0x01;
  VICVectAddr = 0;  
}

void InitSystemMonitor()
{
  TimeInHighLevel = 0;
  WorkRefs = 0;

  /* Initialize Timer 3 */  
  PCONP |= PCTIM3;

  PCLKSEL1 &= ~(3 << PCLK_TIMER3_OFFSET);
  PCLKSEL1 |=  (1 << PCLK_TIMER3_OFFSET);

  T3PR = 6399; // 100 mks  
  T3MR0 = 9999; // 1 s
  T3MCR = 3;

  VICIntEnClr = INTTIM3;
  VICVectAddr27 = (unsigned long)Timer3Handler;
  VICVectPriority27 = 15;  
  

  T3TCR = 0x01;

  VICIntEnable += INTTIM3;
}

void ImWorking()
{
  WorkRefs++;
  
  if (WorkRefs == 1)
  {
    Work_SET();
    TimeSetHighLevel = T3TC;
  }
}

void ImFinished()
{
  if (WorkRefs > 0)
    WorkRefs--;

  if (WorkRefs == 0)
  {
    TimeInHighLevel += T3TC - TimeSetHighLevel;
    Work_CLR();
  }
}
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
AHTOXA
сообщение Aug 10 2011, 10:43
Сообщение #2


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Если вы работаете с какой-то переменной и в основной программе и в прерывании (напр. TimeInHighLevel), то надо её как-то защищать, иначе возможны большие неприятности. Простейший вариант - запрещать прерывания на время обращения к переменной в основной программе.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
whiteTigr
сообщение Aug 10 2011, 10:51
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 25-07-11
Пользователь №: 66 407



Цитата(AHTOXA @ Aug 10 2011, 14:43) *
Если вы работаете с какой-то переменной и в основной программе и в прерывании (напр. TimeInHighLevel), то надо её как-то защищать, иначе возможны большие неприятности. Простейший вариант - запрещать прерывания на время обращения к переменной в основной программе.


Неприятности, если в момент записи в переменную приходит прерывание (т.е. цепочка команд ассемблера разрывается прерыванием)? При возобновлении в регистре, который он хотел записать может оказаться мусор. Я правильно понимаю?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 10 2011, 11:17
Сообщение #4


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(whiteTigr @ Aug 10 2011, 16:51) *
Неприятности, если в момент записи в переменную приходит прерывание (т.е. цепочка команд ассемблера разрывается прерыванием)? При возобновлении в регистре, который он хотел записать может оказаться мусор. Я правильно понимаю?

Ну вот смотрите:
Код
    TimeInHighLevel += T3TC - TimeSetHighLevel;

Здесь происходит считывание значения переменной TimeInHighLevel в регистр, прибавление к нему какого-то значения и запись значения этого регистра в переменную TimeInHighLevel.
Теперь представьте, что после считывания, но перед записью возникло прерывание. А там вот что:
Код
  TimeInHighLevel = 0;

Получается, что это обнуление пропадает, ибо в переменную TimeInHighLevel тут же запишется старое значение TimeInHighLevel, увеличенное на T3TC - TimeSetHighLevel.
Вот так и возрастает подсчитанная загрузкаsm.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
whiteTigr
сообщение Aug 10 2011, 12:02
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 25-07-11
Пользователь №: 66 407



Цитата(AHTOXA @ Aug 10 2011, 15:17) *
Ну вот смотрите:
Код
    TimeInHighLevel += T3TC - TimeSetHighLevel;

Здесь происходит считывание значения переменной TimeInHighLevel в регистр, прибавление к нему какого-то значения и запись значения этого регистра в переменную TimeInHighLevel.
Теперь представьте, что после считывания, но перед записью возникло прерывание. А там вот что:
Код
  TimeInHighLevel = 0;

Получается, что это обнуление пропадает, ибо в переменную TimeInHighLevel тут же запишется старое значение TimeInHighLevel, увеличенное на T3TC - TimeSetHighLevel.
Вот так и возрастает подсчитанная загрузкаsm.gif


Угук, спасибо за разъяснение. sm.gif А то у меня только на подсознательному уровне из книжек отложилось, что нежелательно так делать, а вот до осмысления так и не дошло.

А как запретить прерывания на время записи переменной? И будут ли обработаны пришедшие за это время прерывания?

Ошибка в показаниях нашлась. Таймер был настроен на отсчет по 100 мкс, и получалось так, что без оптимизации длительность сигнлов была больше этого времени, а с оптимизацией слишком сильно сократилась и перестала считаться.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 10 2011, 13:21
Сообщение #6


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(whiteTigr @ Aug 10 2011, 18:02) *
А как запретить прерывания на время записи переменной? И будут ли обработаны пришедшие за это время прерывания?

Зависит от используемого компилятора. Что-то типа disable_irq()/enable_irq().


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
whiteTigr
сообщение Aug 10 2011, 20:18
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 25-07-11
Пользователь №: 66 407



Цитата(AHTOXA @ Aug 10 2011, 17:21) *
Зависит от используемого компилятора. Что-то типа disable_irq()/enable_irq().


Спасибо.

Цитата(kan35 @ Aug 10 2011, 23:37) *
А не проще ли использовать RTOS, в них чаще всего определение загрузки процессора уже заложено, можно даже по отдельным задачам все проанализировать. Например:
http://www.freertos.org/rtos-run-time-stats.html


Посмотрел на скриншот. ОС, судя по всему, откликается по веб-интерфейсу, которого в моей платке и в помине нет.

Идея то у меня банальная:
1) Обнаружить, если мы написали что-то страшное, и оно сожрало все процессорное время;
2) Потренироваться в программировании.

Завтра только допишу блокировку прерываний на время работы с переменной, и, я думаю, будет достаточно.
На последних тестах перед уходом домой показания осцилографа и модуля были примерно одинаковыми.
Go to the top of the page
 
+Quote Post
kan35
сообщение Aug 11 2011, 13:07
Сообщение #8


Знающий
****

Группа: Участник
Сообщений: 537
Регистрация: 22-02-06
Пользователь №: 14 594



Цитата(whiteTigr @ Aug 11 2011, 00:18) *
Посмотрел на скриншот. ОС, судя по всему, откликается по веб-интерфейсу, которого в моей платке и в помине нет.

Идея то у меня банальная:
1) Обнаружить, если мы написали что-то страшное, и оно сожрало все процессорное время;
2) Потренироваться в программировании.

выводить можно хоть как, хоть в компорт, если почитаете, там просто текстовый массив заполняется.
В общем там идея подсчета загрузки примерно такая же как и вы предложили, просто все это твориться без вашего ручного участия. Поделюсь своим опытом, в 100% своих проектов на АРМах я ставлю Ось, по моему иначе такой сильной машиной не реально управлять оптимально, выжимать из нее всю мощность. Отклонился от темы я..
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 22:38
Рейтинг@Mail.ru


Страница сгенерированна за 0.01459 секунд с 7
ELECTRONIX ©2004-2016