глюки в AVR-GCC ?

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From Russian to

Threaded View
Привет Всем !
Есть вопросики. Стал опримизировать прогу на С (AVR GCC) и сталкнулся с
некоторыми непонятными вещами.
1. Каким образом закрепить за переменной указателем регистр? Если у нас
есть переменная типа char - то все понятно - register unsigned char spiW
asm("r3"). Ну а если типа указатель на char ? И я хочу закрепить за
регистрами X или Y.
2. следующий кусок кода:
{
    *(spi_ptr++) = SPDR;
    SPDR = packCnt;
    ++packCnt;
}
ассемблируется в следующий код (с флагом оптимизации -O3) {
            *(spi_ptr++) = SPDR;
 28e:    7f b1        in    r23, 0x0f    ; 15
 290:    71 93        st    Z+, r23
 292:    f0 93 61 00    sts    0x0061, r31
 296:    e0 93 60 00    sts    0x0060, r30
            SPDR = packCnt;
Хотя spi_ptr обьявлен как volatile unsigned char *spi_ptr. Почему же он
не обнавляется на каждом витке цикла ? Тоесть в прерываниях я изменяю
spi_ptr, а реально он не меняется :( В чём же дело ?
3. В том же куске кода непонятно что будет, если произойдет прерывание
между инструкциями sts    0x0061, r31 и sts    0x0060, r30 ? тоесть в ячейке
0x0061 будет новое значение (записаное по прерыванию), а в 0x0060 -
старое ? Как же быть ?
P.S. у меня avr-gcc (GCC) 3.4.1
Спасибо за исчерпывающие ответы :)
--
Отправлено через сервер Форумы@mail.ru - http://talk.mail.ru

Re: глюки в AVR-GCC ?
19-Nov-04 16:46 Alexy Gorbach wrote to All:

AG> 1. Каким образом закрепить за переменной указателем регистр? Если у нас
AG> есть переменная типа char - то все понятно - register unsigned char spiW
AG> asm("r3"). Ну а если типа указатель на char ? И я хочу закрепить за
AG> регистрами X или Y.
 Не знаю, такими вещами не баловался.


AG> 2. следующий кусок кода:
AG> {
AG>     *(spi_ptr++) = SPDR;

AG> Хотя spi_ptr обьявлен как volatile unsigned char *spi_ptr. Почему же он
AG> не обнавляется на каждом витке цикла ?
Одно из распространённых заблуждений. Аналогичное
легендам про const char *ptr и char const *ptr :-)

В данном случае volatile относится не к spi_ptr, а к (*spi_ptr).
Т.е. volatile - та ячейка, на которую указывает указатель.

Для volatile-указателя надо написать

unsigned char * volatile spi_ptr;


AG> 3. В том же куске кода непонятно что будет, если произойдет прерывание
AG> между инструкциями sts      0x0061, r31 и sts       0x0060, r30 ? тоесть
AG> в ячейке
AG> 0x0061 будет новое значение (записаное по прерыванию), а в 0x0060 -
AG> старое ? Как же быть ?
 Ручками заводит критическую секцию (запрещат все для простоты или только
нужное прерывание на время как доставания указателя в регистр,
так и записи его назад). В языке C слово volatile только говорит
компилятору о том, что переменная может измениться "неожиданно" и
нельзя оптимизировать обращения к ней за счёт кеширования в регистрах.
На проблемы неатомарных операций и прерываний действие volatile
не распространяется.

AG> P.S. у меня avr-gcc (GCC) 3.4.1
Вопросы 2 и 3 должны иметь одинаковые ответы для любого C-компилятора.
(а не компилятора С-подобного языка, все тонкости которого известны
только авторам компилятора).

wbr,
--
/* Oleksandr Redchuk, Brovary, Ukraine */
/* real '\x40' real '\x2E' kiev '\x2E' ua     */


Re: глюки в AVR-GCC ?
Hемедленно нажми на RESET, Alexy Gorbach!


 AG> 2. следующий кусок кода:
 AG> {
 AG>     *(spi_ptr++) = SPDR;
 AG>     SPDR = packCnt;
 AG>     ++packCnt;
 AG> }
 AG> ассемблируется в следующий код (с флагом оптимизации -O3) {
 AG>             *(spi_ptr++) = SPDR;
 AG>  28e:    7f b1        in    r23, 0x0f    ; 15
 AG>  290:    71 93        st    Z+, r23
 AG>  292:    f0 93 61 00    sts    0x0061, r31
 AG>  296:    e0 93 60 00    sts    0x0060, r30
 AG>             SPDR = packCnt;
 AG> Хотя spi_ptr обьявлен как volatile unsigned char *spi_ptr. Почему же он
 AG> не обнавляется на каждом витке цикла ?

  А что по-твоему делается в адресах 290, 292 и 296?

 AG> Тоесть в прерываниях я изменяю
 AG> spi_ptr, а реально он не меняется :( В чём же дело ?
 AG> 3. В том же куске кода непонятно что будет, если произойдет прерывание
 AG> между инструкциями sts    0x0061, r31 и sts    0x0060, r30 ? тоесть в ячейке
 AG> 0x0061 будет новое значение (записаное по прерыванию), а в 0x0060 -
 AG> старое ? Как же быть ?

  volatile от прерываний не помогает (никто и не обещал...)
Hужен отдельный вид блокировки, в данном случае проще на пару
команд запретить все прерывания.


--
  Black Lord - NEDO-RUL, NEDO-DEL...

Site Timeline