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

 
 
> Пару вопросов по Си для MCS51, от начинающего...
Lotor
сообщение Jul 8 2007, 15:32
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 476
Регистрация: 3-07-07
Из: Санкт-Петербург
Пользователь №: 28 866



Доброе время суток. Начал тут изучать C для 51-х и возникли глупые вопросы:
1) Как Вы отсчитываете (формируете) боле-мене точные временные интервалы? Допустим надо сформировать задержку в 1 секунду, стандартной функции у Keil'a нет, надо писать самим. Есть ли стандартные приемы? Или надо написать какую-нить простенькую конструкцию аля for (i=40;i>0;i--), посмотреть какой ассемблеровский код ей соответствует после компиляции и затем прикинуть? Или в программном симуляторе засечь? Но это же так тоскливо... Можно ли решить задачу не методом такого подбора?
2) Как массив помещается в память програм? Keil пихает в драгоценное ОЗУ даже при объявлении со спецификатором const.
Буду благодарен за ответы)


--------------------
Ковырял чукча отверткой в ухе, звук в телевизоре и пропал.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
AndreyS
сообщение Dec 10 2008, 08:56
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 235
Регистрация: 28-01-05
Из: Санкт-Петербург
Пользователь №: 2 276



Добрый день.

Не стал создавать новую тему.

Вопрос в следующем. Вернее проблемма.
Дано:
компилятор Keil
C Compiler C51.exe v8.06
Assembler A51.exe v8.00c
Linker/Locator BL51.exe v6.05
Librarian LIB51.exe v4.24
Hex Converter OH51.exe v2.6

Суть проблеммы
В рабочем режиме иногда прошивка виснет. Выяснил, что зависает (зацикливается) она по причине того что локальные переменные процедуры кто-то запорол.
Нашел в карте памяти что данные ячейки относятся еще к двум процедурам (причем там эти переменные тоже локальные). Одна из которых вызывается в прерывании.
Как мне теперь заставить Keil убрать из перекрестных ссылок эти переменные (чтобы они лежали в разных адресах DATA)?
Делать их глобальными внутри одного файла желания нет.

Пока я проверил только локальные переменные в области DATA, быть может такая петрушка есть еще с переменными в области XDATA. Почему Keil их так расположил? Ведь при компиляции он знает какие процедуры попадают в прерывание и по идее должен этим процедурам для локальных переменных выдилять свои адреса. Может нужно что-то указать??

Спасибо.


--------------------
Удачи.
Go to the top of the page
 
+Quote Post
barabek
сообщение Dec 10 2008, 14:18
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 540
Регистрация: 16-08-07
Из: Владивосток
Пользователь №: 29 831



Цитата(AndreyS @ Dec 10 2008, 18:56) *
Суть проблеммы
В рабочем режиме иногда прошивка виснет. Выяснил, что зависает (зацикливается) она по причине того что локальные переменные процедуры кто-то запорол.
Нашел в карте памяти что данные ячейки относятся еще к двум процедурам (причем там эти переменные тоже локальные). Одна из которых вызывается в прерывании.
Как мне теперь заставить Keil убрать из перекрестных ссылок эти переменные (чтобы они лежали в разных адресах DATA)?
Делать их глобальными внутри одного файла желания нет.

Пока я проверил только локальные переменные в области DATA, быть может такая петрушка есть еще с переменными в области XDATA. Почему Keil их так расположил? Ведь при компиляции он знает какие процедуры попадают в прерывание и по идее должен этим процедурам для локальных переменных выдилять свои адреса. Может нужно что-то указать??

Спасибо.

Как я понял, у Вас есть функция которая вызывается из функции обработки прерывания? Если так, то это очень не гуд smile.gif. Для этого нужны очень веские основания. Только в том случае, если Вы эту функцию вызываете еще из другого места. Но эту ситуацию линкер возможно и не отслеживает и нужно в этой функции переменные объявить static, хотя это равносильно глобальной переменной. Да и тем более возможен повторный вход в функцию со всеми вытекающими. Этот вариант отметаем sad.gif
Если же вызов только из прерывания, тогда лучше вобще обойтись без дополнительной функции, все стащить в одно место, в функцию-обработчик. Вы же наверняка пользуетесь using-ами, может быть линкер эти переменные через регистры протащит, будет маленькое счастье smile.gif. А нельзя вобще обойтись в прерывании без обработки, выставив соответствующий флажок и обработать в другом месте?
Go to the top of the page
 
+Quote Post
AndreyS
сообщение Dec 10 2008, 16:08
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 235
Регистрация: 28-01-05
Из: Санкт-Петербург
Пользователь №: 2 276



Цитата(barabek @ Dec 10 2008, 17:18) *
Как я понял, у Вас есть функция которая вызывается из функции обработки прерывания? Если так, то это очень не гуд smile.gif. Для этого нужны очень веские основания. Только в том случае, если Вы эту функцию вызываете еще из другого места. Но эту ситуацию линкер возможно и не отслеживает и нужно в этой функции переменные объявить static, хотя это равносильно глобальной переменной. Да и тем более возможен повторный вход в функцию со всеми вытекающими. Этот вариант отметаем sad.gif
Если же вызов только из прерывания, тогда лучше вобще обойтись без дополнительной функции, все стащить в одно место, в функцию-обработчик. Вы же наверняка пользуетесь using-ами, может быть линкер эти переменные через регистры протащит, будет маленькое счастье smile.gif. А нельзя вобще обойтись в прерывании без обработки, выставив соответствующий флажок и обработать в другом месте?


Огромное спасибо за содержательный ответ.

В прерывании использую процедуру которая вызывается еще и по коду. Суть процедуры сформировать (подготовить запрос на SPI шину и поставить его в очередь). Т.е. по сути - это и флажок и короткий обработчик этого флажка.

Да. Переосмыслил сейчас еще раз свой код и чую буду переделывать обработчик прерывания. smile.gif Да, тут я упустил из внимания возможность повторного вызова процедуры в неблагоприятный момент. smile.gif

Вы подняли мне веки smile.gif

Правда это не отменяет объединения (отображения части переменных по одним и тем же адресам) локальных переменных двух разных процедур (я пока просто перебросил переменные в одной процедуре в XRAM и таким образом развязал эти процедуры).

Буду переписывать обработчик.

Сообщение отредактировал AndreyS - Dec 10 2008, 16:21


--------------------
Удачи.
Go to the top of the page
 
+Quote Post
barabek
сообщение Dec 11 2008, 00:31
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 540
Регистрация: 16-08-07
Из: Владивосток
Пользователь №: 29 831



Цитата(AndreyS @ Dec 11 2008, 02:08) *
Правда это не отменяет объединения (отображения части переменных по одним и тем же адресам) локальных переменных двух разных процедур (я пока просто перебросил переменные в одной процедуре в XRAM и таким образом развязал эти процедуры).

Если две функции не могут вызываться одновременно (случай с прерыванием) - то конечно же пусть они используют одни и те же адреса для локальных переменных. В этом и соль этих переменных в отличии от глобальных. Если посмотреть на листинг то почти в каждой функции для локальных переменных используются регистры. И это очень хорошо, это только плюс компилятору-линкеру. Ведь памяти очень немного smile.gif
Go to the top of the page
 
+Quote Post
AndreyS
сообщение Dec 11 2008, 12:00
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 235
Регистрация: 28-01-05
Из: Санкт-Петербург
Пользователь №: 2 276



Цитата(barabek @ Dec 11 2008, 03:31) *
Если две функции не могут вызываться одновременно (случай с прерыванием) - то конечно же пусть они используют одни и те же адреса для локальных переменных. В этом и соль этих переменных в отличии от глобальных. Если посмотреть на листинг то почти в каждой функции для локальных переменных используются регистры. И это очень хорошо, это только плюс компилятору-линкеру. Ведь памяти очень немного smile.gif


Добрый день.

Спасибо всем за ответы.
Все что Вы ранее высказывали, я прекрасно понимаю.
Но тут вещь в следующем.
Компилятор никогда не отображает локальные переменные на одни и теже адреса, если они пересекаются при вызове процедур (РАЗНЫХ ПРОЦЕДУР). Если переменные пересекаются (отображаются на одни и теже адреса) (РЕГИСТРЫ НАПРИМЕР), то компилятор при входе в такую процедуру сохраняет все эти регистры в стек. Если компилятор этого не делает - то это плохой компилятор. Анализирую код Keil'а он (Кейл) именно так и делает. Если я в перерывании (или процедуре) использую вызов процедуры, то в прерывании, перед ее выполнением, сохряняются все регистры и PSW в стек. Если я неиспользую каких либо регистров (ну компилятор в процессе компиляции ничего не задействовал), то на входе он ничего не сохраняет. Для Кейла я это проверял. Правда весь листинг виден только в самом проце, в выходных файлах этого нет.

В данном примере происходит все именно так.
Если у меня есть ряд процедур, которые могут вызваться из прерывания и у них есть локальные переменные, то компилятор не отражает на адреса этих переменных ничего из других процедур.
В данном примере я заметил пересекающиеся области (две ячейки наложились. Две ячейки локальных переменных разных процедур). Причем ячеки входящих переменных (извиняюсь за корявость, но переменных через которые я передаю данные в процедуру).

Есть функция Spi_RD в которую я передаю ряд параметров. Она вызывается в прерывании.
Есть функция Filtrate_long в которую я передаю одно число и в нутри нее есть переменные счетчики.
Так пересеклись две переменные из входящих переменных функции Spi_RD и внутренние переменные-счетчики процедуры Filtrate_long.

На примере других функций я вижу, что используемые регистры для локальных переменных в процедурах, компилятор сохраняет в стек, при вызове внутри одной процедуры другой (с такими же регистрами). Иначе я вообще никогда не смог бы вызывать внутри процедур другие процедуры. Именно так происходит и тут. Просто количество параметров передаваемых в процедуру Spi_RD наверное большое и они вышли за регистры и компилятор о них забыл (мое предположение).

Вот вызовы процедур с которыми я нашел пересечение переменных:
Код
bit Spi_RD(byte * ptr, byte * complete, word LEN, byte type, byte FIRST_SENT, bit cs);

signed long filtrate_long(signed long input_data);


Пересеклись адреса следующих переменных
type, FIRST_SENT с локальными переменными (счетчиками) внутри функции Filtrate_long.

В данный момент локальные переменные функции Filtrate_long я объявил в области XDATA дабы они попросту ушли из карты памяти в другую область (остальные вроде как ен пересекаются). И все работает без глюков.

Без наездов. Просто пытаюсь разобраться, что я делаю не так. И что мне следует сделать, чтобы такого не происходило впредь.

Ведь я не исключаю того что такое же может произойти в области XDATA.


Цитата(tag @ Dec 11 2008, 13:05) *
Как известно памяти у 51 немного, плюс компилятор разработан так что локальные переменные сохраняет не на стеке, а либо в регистрах, либо в памяти (в этом вы можете убедится просмотрев руководство). В случае когда переменные располагаются в памяти линковщик может перекрывать область памяти локальных переменных одной подпрограммы и такую же область другой подпрограммы. Видимо так сделано с целью экономии памяти. Тогда, конечно подразумевается что эти фукции к примеру, не могут вызывать друг друга из своего тела. Так линковщик работает если ему не указать опцию nooverlay. Когда данная опция указана области локальных переменных подпрограмм не пересекаются и следовательно проблема порчи локальных переменных исчезает.


Добрый день.

Огромное вам спасибо.

Мне кажется - это есть лекарство моей болезни. Так как симптомы вы описали точно.

Черт, а ведь эта директива относится ко всему проекту. С ней области data не хватает smile.gif
А для лечения локально, нужно делать глобальбные переменные. А что же делать с входыми данными процедур??? Тоже глобально??

Сообщение отредактировал AndreyS - Dec 11 2008, 12:11


--------------------
Удачи.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Lotor   Пару вопросов по Си для MCS51   Jul 8 2007, 15:32
- - alcosar   Цитата(Lotor @ Jul 8 2007, 18:32) Доброе ...   Jul 8 2007, 19:51
|- - Lotor   Цитата(alcosar @ Jul 8 2007, 23:51) const...   Jul 9 2007, 16:18
|- - msn   Цитата(Lotor @ Jul 9 2007, 19:18) Это-то ...   Jul 10 2007, 21:25
||- - zltigo   Цитата(msn @ Jul 11 2007, 00:25) пишем......   Jul 10 2007, 22:57
|- - Sir Jon   Цитата(Lotor @ Jul 9 2007, 19:18) Это-то ...   Sep 7 2007, 10:51
|- - kolobok0   Цитата(Sir Jon @ Sep 7 2007, 14:51) ..Хор...   Sep 7 2007, 11:18
- - SALOME   Цитата(Lotor @ Jul 8 2007, 22:32) Доброе ...   Jul 9 2007, 03:46
- - oran-be   ЦитатаЭто-то понятно, но есть вагон и маленькая те...   Jul 9 2007, 18:17
|- - Lotor   Цитата(oran-be @ Jul 9 2007, 22:17) ...   Jul 9 2007, 19:21
|- - Sergu   Цитата(Lotor @ Jul 9 2007, 22:21) Еще воз...   Jul 10 2007, 03:51
|- - Lotor   Цитата(Sergu @ Jul 10 2007, 07:51) удобно...   Jul 10 2007, 16:53
- - silc   alcosar: const и не должен помещать в ОЗУ. Вам нуж...   Aug 10 2007, 14:57
- - Василий_Безкатегорийный   Насчет побитового обращения к портам. Я пытаюсь ра...   Sep 25 2007, 08:45
|- - tag   Цитата(barabek @ Dec 11 2008, 04:31) В эт...   Dec 11 2008, 10:05
||- - barabek   Цитата(tag @ Dec 11 2008, 20:05) Уверяю в...   Dec 11 2008, 10:53
|- - barabek   Цитата(AndreyS @ Dec 11 2008, 22:00) Комп...   Dec 11 2008, 14:00
|- - AndreyS   Цитата(barabek @ Dec 11 2008, 17:00) Здес...   Dec 11 2008, 14:37
- - AndreyS   Люди!!! Помогите. Пока перебросил пере...   Dec 10 2008, 10:57
- - Axel   Если функция не написана, как реентерабельная (сло...   Dec 10 2008, 17:37
- - AndreyS   Добрый день. Написал для прерывания специальную ф...   Dec 12 2008, 10:38
- - Сергей Борщ   Цитата(AndreyS @ Dec 12 2008, 12:38) И пе...   Dec 12 2008, 12:03
- - c8051   Цитата(Сергей Борщ @ Dec 12 2008, 15:03) ...   Dec 12 2008, 16:52
- - Сергей Борщ   Цитата(c8051 @ Dec 12 2008, 18:52) c51.pd...   Dec 12 2008, 18:37
- - AndreyS   Цитата(Сергей Борщ @ Dec 12 2008, 21:37) ...   Dec 13 2008, 20:34


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

 


RSS Текстовая версия Сейчас: 29th July 2025 - 07:18
Рейтинг@Mail.ru


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