FAQ: Keil C51

Вопросы по работе с Keil C51 (Keil µVision2)

Составитель:Александр Бельченко
Дата: 10 августа 2006
Сайт:http://OnEmbedding.com
URL:http://OnEmbedding.com/tools/keil/faq/

Содержание


1   Общие вопросы

1.1   Где взять Keil C51?

На официальном сайте www.keil.com можно скачать оценочную версию пакета. Для этого нужно заполнить небольшую анкету (обязательные поля выделены полужирным шрифтом). После заполнения анкеты вы получите ссылку на скачивание файла. Ссылка эта временная, генерируется каждый раз случайно. Закачивать необходимо без обрыва связи, в один поток.

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

1.2   Где взять описание компилятора C51, ассемблера A51 и линкера?

После установки пакета Keil C51 все необходимые файлы справки вы сможете найти в каталоге:

{BaseKeil}\C51\Hlp,

где {BaseKeil} — каталог, в который установлен пакет (по умолчанию: C:\Keil).

Также вся документация доступна для вызова из интегрированной среды µVision2. Для этого в окне проекта (Project Window) перейдите на закладку Books. Искомая документация находится в ветке Tools User's Guide.

  • Описание Си компилятора — C51 User's Guide (c51.pdf)
  • Описание ассемблера, линкера, библиотекаря и других вспомогательных утилит — Assembler/Utilities (a51.pdf)
  • Документ "Начинаем работу с µVision2" — µVision2 Getting Started (gs51.pdf)
  • Справка по библиотечным функциям C51 — C51 Library Function (c51lib.chm)
  • Справка по командам отладчика — µVision2 Debug Commands (dbg51.chm)
  • Справка по RTOS RTX51 Tiny — RTX51 Tiny User's Guide (tr51.chm)
  • Справка по монитору FlashMonitor51 — Flash Monitor (flashmon51.chm)
  • Справка по внутрисистемному отладчику ISD51 — ISD51 In System Debugger (isd51.chm)
  • Справка по кодам предупреждений/ошибок компилятора и линкера — (errors.chm)

1.3   Есть ли переводы документации на русский язык?

Официальных переводов нет. Маленькие части некоторых документов переведены А. Бельченко и выложены на сайте On Embedding.

1.4   С чего начать освоение Keil C51?

  1. С чтения документа "Getting Started with µVision2" ("Начинаем работу с µVision2") и освоения большого числа примеров, поставляемых в комплекте среды. Примеры программ можно найти в каталоге:

    {BaseKeil}\C51\Examples
    

где {BaseKeil} -- каталог, в который установлен пакет (по умолчанию: C:\Keil).

  1. На странице Микушина Александра Владимировича, преподающего в СибГУТИ, можно найти учебное пособие "Программирование на языке С51".

2   Вопросы программирования (HowTo)

2.1   Как на Си проинвертировать битовую переменную? Например, ножку порта?

Используйте конструкцию вида:

bitvar = !bitvar,

где bitvar — битовая переменная.

2.2   Как в исходном тексте на Си сделать ассемблерные вставки?

В теле ваших функций вы можете использовать ассемблерные вставки. Для этого начало и конец вставки необходимо выделить парой директив:

#pragma asm
        ; код на ассемблере
#pragma endasm

В менеджере проекта необходимо задать для Си-файла с ассемблерными вставками следующие опции:

  • Generate Assembler SRC File
  • Assemble SRC File

Замечание: файл, содержащий главную функцию программы main(), не может содержать ассемблерных вставок. Выделяйте функции с ассемблерными вставками в отдельные файлы.

Дополнительные сведения, которые необходимо знать при использовании ассемблерных вставок, вы найдете в документе "Cx51 Compiler" ("Компилятор Cx51") в главе 6 "Advanced Programming Techniques" в разделе "Interfacing C Programs to Assembler".

2.3   Как разместить серийный номер/имя прошивки по фиксированному адресу в теле программы?

Используйте директивы линкера для размещения требуемой информации по фиксированному адресу. Подробнее читайте в статье "Расположение переменных по абсолютному адресу (на примере строк в памяти программ)" и в разделе "Linker Location Controls" документа "Cx51 Compiler" (c51.pdf).

2.4   Как на Си написать обработчик прерывания?

Для этого функцию-обработчик необходимо объявить следующим образом:

void  func_name(void) interrupt N using R
{
        // тело функции
}

Здесь:

  • func_name — имя функции-обработчика прерывания (аналогично обычным функциям)
  • interrupt — ключевое слово, указывающее компилятору, что это обработчик прерывания
  • N — номер вектора прерывания по порядку, начиная со сброса (определяет адрес точки входа в прерывание)
  • using — ключевое слово, определяющее какой банк регистров R0-R7 будет использоваться в прерывании
  • R — номер банка регистров для использования в прерывании

Компилятор С51 автоматически генерирует инструкции для сохранения (и последующего восстановления) на стеке всех регистров, которые могут быть изменены в прерывании. А также генерирует автоматическое переключение на указанный ключевым словом using банк регистров при входе в обработчик и возврат к предыдущему банку регистров при выходе из обработчика.

2.5   Использование ключевого слова using в определениях функций

Ключевое слово using является расширением языка Си в реализации C51. using позволяет указывать компилятору, что при входе в данную функцию необходимо переключить текущий банк регистров на указанный, а при выходе из функции — восстановить старый. Наиболее часто using используется при определениях функций-обработчиков прерываний.

2.5.1   Что дает использование using в обработчиках прерываний?

В коде, генерируемом компилятором C51 регистры R0-R7 активно используются как для вычислений, так и для передачи параметров в вызываемые функции. Поэтому необходимо следить, чтобы обработчик прерывания не "испортил" регистры, используемые основным потоком программы. Наиболее просто это сделать, если при входе в прерывание переключиться на другой банк регистров.

Поскольку в процессорах семейства MCS-51 имеется возможность использовать до 4х банков регистров, то целесообразно использовать банк 0 (по умолчанию) для работы основного потока программы, банк 1 — для обработчиков прерываний с низким приоритетом, а банк 2 — для обработчиков прерываний с высоким приоритетом. Банк регистров 3 иногда используется некоторыми RTOS для своей работы.

2.5.2   Предосторожности при использовании using

Когда вы вызываете из функции (например, обработчика прерывания), для которой указано ключевое слово using, другую функцию, то возможно возникновение одного неприятного эффекта, связанного с прямой адресацией регистров. Подробно этот эффект описан в статье "Keil C51. Расширения языка Си. Ключевое слово using: тонкости использования". Для того, чтобы обезопасить себя от подобных эффектов, можно в настройках проекта указать опцию компилятора "Don't use absolute register accesses". Однако при этом несколько увеличится размер кода программы и немного понизится быстродействие почти всех функций.

Дополнительными побочными эффектами при использовании using являются:

  1. Для хранения предыдущего номера банка регистров используется 1 байт на стеке;
  2. Функция, определенная с using, не может возвращать значение типа bit.

2.6   Управление размером стека

В компиляторе Keil C51 принято соглашение о том, что стек располагается в самом конце свободной памяти IDATA и занимает всю оставшуюся область памяти (аппаратный стек в х51 растет вверх). Компилятор не вычисляет требуемый размер стека ввиду того, что эта задача является глубоко нетривиальной. Разработчик программы должен сам оценить требуемый размер стека с учетом возможных прерываний, сохранения параметров на стеке и проч.

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

Для того, чтобы задать минимальный размер стека, необходимо в стартап-файле (Startup.a51 или специфичный для конкретного процессора) найти следующее объявление сегмента стека:

?STACK          SEGMENT   IDATA

                RSEG    ?STACK
                DS      1

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

2.7   Квалификаторы для явного указания области памяти размещения переменной

Одним из расширений языка C51 является наличие набора квалификаторов для явного указания области памяти, в которой необходимо разместить переменную.

  • data — размещение во внутреннем ОЗУ процессора, младшие 128 байт. Обращение посредством прямой адресации и косвенной адресации через индексные регистры R0, R1 (инструкции процессора пересылки данных MOV @R0).
  • idata — размещение во внутреннем ОЗУ процессора, все 256 байт. Обращение только посредством косвенной адресации через индексные регистры R0, R1 (инструкции процессора пересылки данных MOV @R0).
  • bdata — размещение в побитно адресуемой области памяти внутреннего ОЗУ (адреса 0x20-0x2F)
  • pdata — размещение во внешней памяти. Размер памяти ограничен 256 байтами. Доступ посредством косвенной адресации через индексные регистры R0, R1 (инструкции процессора пересылки данных MOVX @R0).
  • xdata — размещение во внешней памяти. Размер памяти ограничен 64 КБ. Доступ посредством косвенной адресации через индексный регистр DPTR (инструкции процессора пересылки данных MOVX @DPTR).
  • code — размещение константных данных в области памяти программ. Размер памяти ограничен 64 КБ. Только чтение данных посредством косвенной адресации через индексный регистр DPTR или регистр PC и указание смещения в аккумуляторе ACC (инструкции процессора MOVC A,@A+DPTR; MOVC A,@A+PC).
  • far — внешняя память данных, адресация до 16 МБ.

Для определения SFR регистров используются квалификаторы sfr и sfr16 (для байтовых и двухбайтовых переменных соответственно).

2.8   Использование битовых переменных типа sbit, объявленных в другом модуле

Ключевое слово sbit является расширением языка C51 и позволяет задавать битовые переменные в побитово адресуемой области памяти. Для определения конкретного бита в байте, размещенном в побитово адресуемой области памяти, необходимо использовать следующую декларацию:

sbit  bitname = bdatavar ^ N;

Здесь:

  • sbit — ключевое слово;
  • bitname — имя битовой переменной;
  • bdatavar — переменная, расположенная в побитно адресуемой области памяти;
  • N — номер бита в переменной bdatavar, отсчет начиная с 0.

Важным условием является размещение определения переменной bdatavar в том же Си-файле, где производится объявление переменной типа sbit. Для определения переменной, которая должна размещаться в побитно адресуемой области памяти, используется квалификатор bdata:

type bdata name;

Здесь:

  • type — тип переменной. Если предполагается, что эта переменная будет побитно адресуемой, то тип ограничен только целыми: char, short, int, long.
  • bdata — квалификатор, указывающий на расположение переменной в побитно адресуемой области BDATA;
  • name — имя переменной.

Если вы хотите, чтобы объявленные в одном модуле переменные типа sbit могли быть доступны в других модулях, то в этих модулях вам необходимо дать объявление внешней битовой переменной:

extern bit bitname;

Заметьте, что при объявлении внешней переменной используется тип bit, а не sbit.

См. "Trouble with the bdata Memory Type" стр.378 в руководстве компилятора C51.

2.9   Использование внешней памяти данных FAR

Проблема: При попытке размещения больших массивов в области памяти FAR, компилятор выдает ошибки, несмотря на то, что размер памяти FAR ограничен сверху 16МБ.

Причины:

  1. Массивы больше 64КБ использовать нельзя. Keil µVision2 не позволяет объявлять объекты, размер которых превышают 64КБ:

    http://www.keil.com/support/man/docs/c51/c51_le_farmem.htm

  2. Массив должен целиком располагаться в перделах одной 64КБ страницы. Размещение объектов, пересекающих границу 64КБ, не допускается:

    http://www.keil.com/support/docs/2663.htm

  3. Привязка размещения массива к конкретному адресу в области FAR должна выполняться при помощи FARRAY:

    http://www.keil.com/support/man/docs/c51/c51_farray.htm

Отвечал: Snaky (конференция на http://www.caxapa.ru)


3   Вопросы отладки

3.1   Как при отладке определить максимальный требуемый размер стека?

Максимальное значение указателя стека SP запоминается в специальной служебной переменной sp_max, которую можно увидеть, открыв закладку Regs в окне проекта (Project Window).

Для определения размера стека, который необходим для вашей программы, нужно проимитировать выполнение этой программы в симуляторе для разных ветвей программы, проимитировать вызов прерываний. После этого значение sp_max можно использовать для оценки необходимого размера стека.

3.2   Можно ли в отладчике увидеть/изменить состояние периферии процессора?

Да. Чтобы посмотреть состояние конкретного периферийного узла, откройте его окно при помощи соответствующего пункта меню Peripheral. Вам доступны для просмотра и изменения параметры системы прерываний, портов ввода-вывода, UART, таймеров и другой дополнительной периферии (такой как АЦП/ЦАП и др.)

3.3   Как в отладчике можно симулировать работу внешних устройств, подключенных к отлаживаемому процессору?

Для имитации логики работы несложных устройств или для имитации части их функциональности можно воспользоваться отладочными функциями (Debug Functions). О том что это такое и как их использовать подробно описано в 6й главе документа "Getting Started with µVision2" (перевод на русский язык 6й главы).

Более продвинутым и мощным средством является создание специальной динамической библиотеки, которая будет подключаться к симулятору µVision2 и имитировать все тонкости работы внешнего устройства.

Как создавать дополнительные отладочные библиотеки (DLL) описано в Application Note 154 "Implementing DLLs for User-defined Simulation (AGSI)".

Готовые DLL различного назначения можно взять на следующих сайтах:

  • Extension DLLs for µVision2 (большое число различных DLL для некоммерческого и невоенного использования)

3.4   Как загрузить в отладчик для симуляции готовый бинарный файл прошивки?

Если у вас есть готовый бинарный (в двоичном коде) файл прошивки и вы хотите просимулировать его работу, то сначала его необходимо преобразовать в hex-формат при помощи утилиты bin2hex, а затем уже полученный hex-файл загружать в симулятор при помощи команды Load, например:

LOAD MYFILE.HEX

4   Известные глюки

4.1   Куда пропадают русские буквы э и я?

При компиляции программ в строках пропадают буквы э и/или я. Эта проблема каким-то образом связана с системными библиотеками Windows, потому что на разных машинах этот эффект проявляется неодинаково.

Решением этой проблемы является использование вместо букв э и я восьмеричных или шестнадцатеричных констант:

Буква Восьмеричный код Шестнадцатеричный код
э \375 \xFD
я \377 \xFF

Для автоматизации этой замены можно воспользоваться утилитой pyLCDstring.

4.2   Keil не хочет работать в WindowsXP?

Проблема: Keil µVision2 не хочет работать в WindowsXP.

Признаки: При входе в Windows пользователь вводит логин (имя), содержащее русские буквы. В результате µVision2 отказывается нормально компилировать/собирать программу.

Причина: Windows использует логин пользователя для формирования имени специальной папки, в которой хранятся настройки данного пользователя. Обычно имя такой папки в Windows семейства NT (2000/XP) выглядит так:

C:\Document and Settings\username

Последняя часть пути (username) совпадает с логином пользователя.

Если пользователь использует русский логин, (например, Саша), то и путь к папке с настройками пользователя будет содержать русские буквы.

Проблема заключается в том, что в папке с настройками находится так называемая папка для временных файлов (TEMP). Keil µVision2 использует папку для временных файлов для своих нужд при компиляции/сборке проекта. И, путь к папке, содержащий русские буквы, вызывает внутреннюю ошибку в компилятре/линкере Keil.

Решение: принудительно установить другой путь к папке с временными файлами; путь, в котором будут присутствовать только латинские буквы/цифры.

  1. Создайте папку для временных файлов, например C:\Temp
  2. Откройте настройки переменных среды пользователя: Пуск -> Настройка -> Панель управления -> Система. Перейдите на вкладку Дополнительно и щелкните по кнопке Переменные среды.
  3. В верхней половине открывшегося диалога вы увидите набор переменных текущего пользователя.
  4. Найдите в этом списке переменные TEMP и TMP. Двойным щелчком по каждой из них запустите редактирование значения. Измените значение переменной на полный путь к новой папке для временных файлов (например, C:\Temp).
  5. По окончании редактирования закройте диалоги.
  6. Перезапустите Keil µVision2. Теперь он должен использовать новые настройки переменных окружения.