ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Вторник
26 ноября
62448 Топик полностью
Romario (08.07.2006 17:20, просмотров: 1) ответил Rostu на Практически Советы KEIL C51 исскуство программирования
попробую чегонибудь сказать:)  KEIL в разных задачах TASK резервирует одно и тоже место в RAM. Поетому столкнулся со следующим запускается подпрограмма1 из TASK1, в ето время ее прерывает TASK2 (что норнально для RTX51) и подпрограмма2 из TASK2, переписывает данные в подпрограмме1. Долго все проверял пока я ето понял. Теперь панический ужас, что делать, как защититься от такого. Попытался убать оптимизацию(была уровень 7),перестала работать вся программа Я в шоке, что делать дальще. такого быть не может, ибо у каждой задачи своя область памяти которая "прописывается" ей при ее инициализации. Если такое происходит, то видимо Вы на какую то задачу выделили мало памяти и это задача залезает на память, предназначенную для другой задачи. Попробуйте выделить чуть более памяти. Также можно иногда контролировать что задача не превысила лимит отведенной ей памяти а именно: обнулите память предназначенную для некой задачи при инициализации задачи. Потом гденибудь в программе вызывайте монитор, который ищет первый не 0 во всех областях памяти для каждой задачи. по номеру первого не 0 можно судить сколько осталось памяти. Вместо нулевой инициализации можно инициализировать последовательность 0x00,0x01,0x02... как только последовательность нарушена, значит до того места задача занимала память. 2. И еще KEIL выдает предупреждение, что например TASK1 и TASK2 вызывают одну и ту же подпрограмму. В одних случаях для меня ето не критично в других критично. Что делать? Если функции реентранты (т.е. не используют глобальные переменные для своей работы и работают только на стеке) то их можно вызывать из разных задача сколько угодно. Также они не должны обрабатывать (из разных задача) одну и туже информацию. Если обеспечить такое "разделение" невозможно, то необходимо сделать эти функции т.н. "защищаемыми ресурсами" у RTX51 должны быть соответсвтующие сервисы а именно: семафоры, мутексы, флаги и т.д. т.е. перед вызовом критической функции Вы сообщаете системе что занимаете ресурс, по кончании вызова Вы сообщаете системе что ресурс освобожден. Если какая то другая задача хочет вызвыать эту функцию она проделывает аналогичные действия но уже при попытке захвата ресурса система сообщит ей что он уже занят и необходимо подождать. (все это делается внутренними сервисами системы) 4. Надо ли бояться долгих прерываний и как их распознать? Бояться долгих прерываний (имеется ввиду обработчки прерывания?) надо и очень сильно:) Распознать их невозможно, их просто надо правильно кодировать:) а именно обработка прерываний должна быть минимальна по функциональности, остальную работу должна делать основаня задача. Из прерываний нужно только сигнализировать основной задаче о возникновении собственно самого прерывания ну плюс обработать/сбросить/инициализировать хардварные вещи которые эти прерывания генерят. все. Если мипсы проца позволяют, то не возбранаяется поделать в обработчике чего нибудь еще. Но тут надо аккуратно. 5. При работе с медленной памятью SPI EEPROM, как не потерять данные. Как не тормозить выполнение других задач? передача в SPI память не бывает медленной. Бывает медленная запись, например, в туже EEPROM. Если Вы используете RXT51 (насколько я понимаю это ОС для 51 процев) то запись в EEPROM в текущей задаче не будет тормозить другие задачи, они будут вызываться "сами" либо по тику либо когда им одать управление. Тут главное не переборщить с приоритетом той задачи, которая занимается записью в память. Однако можно поступить другим путем а именно, не сидеть в одном цикле и ждать когда же все передасться да еще и запишется в еепром а сделать процедуру которая имеет сосотояния типа: 1) передача очередного байта (запись в SPI) 2) проверка окончания передачи байта по SPI 3) ожидание записи в память (по окончании всей передачи). При кадом проходе данная процедура вызывается и анализирует текущее состояние процесса записи в EEPROM. Тормозов 0! они будут не больше не меньше тормозов остальных процедур программы. Пример этой процедуры такой:

#define TX_SPI               0 // передача в SPI контроллер
#define TX_SPI_QRY           1 // ожидание окончания передачи
#define WAIT_EE_WR_COMPLEATE 2 // ожидание окончание записи в EEPROM
#define SPI_FREE             3 // свободное состояние

void SPI_FSM (void) {

   switch (ee_wr_st) {
     case TX_SPI:
          spi_wr(byte);
          ee_wr_st = TX_SPI_QRY;
   
     case TX_SPI_QRY:   
     	  if (spi_tx_end() == 0) {
     	    break;
     	  }
     	  if (all_spi_tx() == 1) {
     	    ee_wr_st = WAIT_EE_WR_COMPLEATE;
     	  } else {
     	    ee_wr_st = TX_SPI;
     	  }
   
     case WAIT_EE_WR_COMPLEATE;
     	  if (ee_write_done() == 1) {
     	     ee_wr_st = SPI_FREE;
     	  }
     	  break;
     	  
     case SPI_FREE;
          break;     	  
   
   }
 }
 
 В основном цикле просто вызывает эту процедуру
 SPI_FSM();
5. При работе с медленной памятью SPI EEPROM, как не потерять данные. 1) чтобы при выключении питания прибора целостность данных не "похерилась" и в зависимости от степени важности данных поступается следующим образом: - каждая важная функциональная часть информации должна иметь 2 копии во внешей памяти - каждая копия должна быть защищена контрольной суммой. При обновлении информации ( записи): апдейтиться сразу 2 копии во внешней памяти. При считывании: Ищется первая целостная копия во внешней памяти, она считывается в ОЗУ. Другая копия автоматически перезаписывается. Можно также проверить на "валидность" и равенство автоматически перезаписываему копию и не перезаписывать ее если она верна (например в огрниченном ресурсе памяти) В чем преимущество данного метода? Он позволяет вернуться к предыдущей правильной копии данных в случае, если текущая запись сорвалась по каким либо причинам. Если прибор не ставится в систему обеспечения жизнедеятельности:) и управлением атомных реакторов, то я думаю ничего страшного если не состояится запись в еепром текущей пришедшей информации в момент пропадания питания у прибора. Все равно (по теории вероятности:)) это неизбежно и когда нибудь случиться. Можно еще применить схемотехнические методы для решения данной проблемы а именно - анализ внешнего питания и использование резервного малоемкого источника питания при пропадании внешнего питания (конденсатор, ионистр и т.д.) достаточного для заврешения процедуры записи и приведение переменых программы в состояние "отключение". 2) вместо медленной eeprom можно взять т.н. FRAM которая не имеет задержки при записи. Однако емкость fram более 32К еще не сделали, но если более и не надо, то ее можно использовать вчистую как замену eeprom. 3. Понасоздавал я огромных массивов, чтоб сохранить САN сообщения. Как в классике- больщой буффер для каждого канала. Теперь нехватает RAM(2К). Период прихода сообщений известен, есть САN протокол. Может достаточно по прерыванию сохранять сообщение в массиве программы, без буффера. Или пришло сообщение прерывание закрывает канал. Потом через время другая TASK считывает из канала даные и вновь разрещает прием данных из САN. Что посоветуете? Проблема понятна и известна. Всегда хочется подстраховаться и выделить максимум памяти. Однако она стачична и потом становится ясно, что основное время эта память не используется. Выход из этой ситуации - использовать динамическое размещение памяти. т.е. выделяется общий размер для входных сообщений некоего разумного размера и обзывается это все кучей (heap) Далее с помощью функции mem_alloc и mem_free из кучи память по мере надобности и необходимого размера забирается, и после обоаботки возвращается обратно в кучу. кажется у RTX51 есть сервисы для работы с кучей под OC но если и нет, то библиотека динамического распределения памяти входит в состав среды KEIL. Удачи!