Ревич, Ю.В. Программирование микроконтроллеров AVR: от Arduino к ассемблеру
Глава 7. Система команд АVR 183 При всех подобных манипуляциях с абсолютными адресами с помощью команд ld/lds и st / sts нужно внимательно следить за двумя моментами : во-первых, за тем, чтобы не залезть в уже занятую область памяти, во-вторых, чтобы не испор тить стек. Как мы уже говорили (см. разд. «Память данных» главы 2), младшие ад реса SRAМзаняты регистрами, и запись, например, по адресу $ 0 0 0 0 (zн = о, ZL = о) равносильна записи в регистр rO. Во всех относительно старых моделях, имеющих 64 РВВ, регистровый файл заканчивается адресом в памяти $5F. Сюда относятся «наши» ATmega8, ATmega8535 , ATtiny23 1 3 , а также популярный ATmega 1 6 и дру гие. Поэтому начальный адрес, с которого начинается пользовательская SRAM, и к которому вы можете обращаться без опаски, равен $ 6 0 (десятичное 96, констан та sмм_sтАRт ) . Если объем SRAM составляет 1 024 байта, как в ATmega8, то конеч ный адрес будет $ 0 4 5 F ( 1 1 1 9) . Тогда zн в нашем примере может иметь значения только О, 1 , 2, 3 или 4 . Самое правильное, конечно, пользоваться константой SRAМ _sтАRт, которая во всех моделях указывает на начало пользовательской области SRAМ (так же, как на ее конец указывает RAМE ND). В этом случае вместо заданной нами константы Addres s в листинге 7 . 8 просто подставляется заданная свыше SRAМ_START. Причем, если ко личество данных невелико (меньше, чем $ FF - $ 6 0 = 1 59 байт), можно один раз в начале программы задать zн = High ( SRAМ _ START ) (или, что в нашем случае без раз ницы, просто равным нулю), а потом задавать только ZL = Low ( SRAМ _ START ) . Но это не убережет вас от того, чтобы залезть в самый конец SRAМ, где размеща ется стек, - компилятор его размер предсказать не может, потому никаких указа ний на ошибку не последует. Срыв стека - это типичная ошибка времени выпол нения. ВНИМАНИЕ/ Обязательно нужно помнить, что если в программе имеются вызовы процедур и пре рываний , то последние адреса SRAM использовать нельзя, - мы сами даем в начале программы команду выделить их под стек. Если мы не слишком хулиганим со всякими push/pop и ограничиваемся простыми вызовами подпрограмм с небольшой степенью вложенности (типа вызова какой нибудь процедуры из обработчика прерывания, не более), то для стека с запасом достаточно пространства в десяток байтов. Иначе нужно внимательно смотреть, что и куда вы помещаете (еще раз напомним первую компьютерную аксиому: «За кладывая что-то в память компьютера, помните, куда вы это положили»). Подведем итог, чтобы не запутаться. Самые младшие 32 адреса памяти (от от $ 0 0 до $ 1 F) занимает регистровый файл РОН. Младшие 32 РВВ, с номерами от $ 0 0 до $ 1 F (занимающие адреса памяти от $ 2 0 до $ З F), позволяют напрямую устанавливать значения битов командами sЬi / cЬi . К следующим 32-м РВВ с номерами до $ ЗF (адресами до $ 5F) применимы команды переноса in/out (они применимы ко всем 64-м РВВ, но практически используются преимущественно для старших 32-х) . По этому в старших РВВ значения битов устанавливают через перенос в обычный РОН и загрузку обратно. К первой (младшей) группе всегда относятся, например, реги стры портов Portx и DDRX (а также и битовый массив Pinx), потому с ними проще
Made with FlippingBook
RkJQdWJsaXNoZXIy MTExODQxMg==