Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум разработчиков электроники ELECTRONIX.ru _ IAR _ Регистры сравнения через указатель

Автор: Ga_ry Jul 8 2018, 12:47

Здравствуйте, почему не работает такой код, что я еще не дописал?
Вверху глобальной переменной OCR инициализирован массив, которому присвоены адреса 6-ти регистров сравнения атмега48, а внизу процедура (цикл убрал) в которой по циклу необходимо присваивать значения в выбранный регистр.
Если имя массива и есть указатель на массив, то почему нижняя строка идет как ошибка?

 

Автор: Jenya7 Jul 8 2018, 13:44

Цитата(Ga_ry @ Jul 8 2018, 18:47) *
Здравствуйте, почему не работает такой код, что я еще не дописал?
Вверху глобальной переменной OCR инициализирован массив, которому присвоены адреса 6-ти регистров сравнения атмега48, а внизу процедура (цикл убрал) в которой по циклу необходимо присваивать значения в выбранный регистр.
Если имя массива и есть указатель на массив, то почему нижняя строка идет как ошибка?


уберите *. просто OCR[0]

Автор: Ga_ry Jul 8 2018, 14:12

Цитата(Jenya7 @ Jul 8 2018, 16:44) *
уберите *. просто OCR[0]

Вы шутите?

Автор: technik-1017 Jul 8 2018, 14:45

OCR это не РЕГИСТРЫ сравнения, а ПОРТЫ, вы пытаетесь обратиться к портам по указателю? Или какая цель этого кода? Что вы хотите получить?
Наверно необходимо преобразование типа OCR до типа определения портов, чтобы компилятор понял, что это не адресное пространство RAM

почитайте здесь (2. Передача порта через указатель)
http://electronix.ru/redirect.php?http://easyelectronics.ru/rabota-s-portami-vvoda-vyvoda-mikrokontrollerov-na-si.html

Автор: VladislavS Jul 8 2018, 14:53

Если вы хотите элементы массива использовать как адрес, то надо сделать приведение типа именно к тому адресному пространству, куда вы хотите обратиться. У AVR их много разных, компилятор сам не угадает что от него хотят. Посмотрите как в заголовочных файлах порты прописаны.

Автор: Ga_ry Jul 8 2018, 15:35

Цель - 6 аппаратных каналов шим. Присваивая определённому регистру сравнения число 8 бит, я получаю управления скважностью шим.
В заголовочных файлах это прописано так:
SFR_B_R(0xB4, OCR2B)
SFR_B_R(0xB3, OCR2A)
SFR_W_R(0x8A, OCR1B)
SFR_W_R(0x88, OCR1A)
SFR_B_R(0x28, OCR0B)
SFR_B_R(0x27, OCR0A)

Автор: VladislavS Jul 8 2018, 16:49

Цитата(Ga_ry @ Jul 8 2018, 18:35) *
SFR_B_R(0xB4, OCR2B)

Ну а дальше пройтись и посмотреть что это значит не судьба?

Небольшая цитатка из документации, чтобы осознать глубину задачи. Звёздочкой тут не отделаться, это вам не ARM.
Цитата
Memory attributes
A memory attribute corresponds to a certain logical or physical memory in the
microcontroller.
Available function memory attributes:
__nearfunc, __farfunc
Available data memory attributes:
__tiny, __near, __far, __huge, __regvar, __eeprom, __tinyflash, __flash,
__farflash, __hugeflash, __generic, __io, and __ext_io.
Data objects, functions, and destinations of pointers or C++ references always have a
memory attribute. If no attribute is explicitly specified in the declaration or by the
pragma directive #pragma type_attribute, an appropriate default attribute is
implicitly used by the compiler. You can specify one memory attribute for each level of
pointer indirection.

Автор: Ga_ry Jul 8 2018, 17:25

VladislavS, Вы можете дать код который будет работать именно для этого случая?

Автор: VladislavS Jul 8 2018, 17:27

Нет, я сейчас не занимаюсь AVR. Просто по старой памяти sm.gif

Хотя нет, могу.

Код
OCR0A = pwm_tab[idx1];

Автор: Ga_ry Jul 8 2018, 17:59

VladislavS, понятно, спасибо.
Это у меня и так работает.

Автор: VladislavS Jul 8 2018, 18:02

Да блин, ну я же цитату с документации не зря привёл!

Код
  const uint8_t reg = 0x27;
  *(__io uint8_t *)reg = 0x55;


Код
//   12   *(__io uint8_t *)reg = 0x55;
        LDI     R16, 85
        OUT     0x27, R16


Для массива сами раскрутите...

Автор: Ga_ry Jul 8 2018, 18:54

Извиняюсь, цитату я как раз пропустил читаю с телефона.

Нет, все равно не идет даже без массива:

Код
const unsigned char
  OCR = 0x27;
void cycle_1(void)
{
  *(__io unsigned char *) OCR = pwm_tab[idx1];
}

Строки с ошибкой теперь не выделяются а просто в сообщениях компилятор пишет.
Tool Internal Error:
Internal Error: [CoreUtil/General]: Illegal state

Это точно для iar avr?

Автор: VladislavS Jul 8 2018, 18:59

Цитата(Ga_ry @ Jul 8 2018, 21:54) *
Это точно для iar avr?

Точнее не бывает. И с массивом тоже работает. idx1 как определено?

Автор: Ga_ry Jul 8 2018, 19:17

idx1 глоб. 8 бит без знака

Автор: megajohn Jul 8 2018, 19:32

Цитата(Ga_ry @ Jul 8 2018, 16:47) *
Здравствуйте, почему не работает такой код, что я еще не дописал?


вот такой код в иаре компилится и должен работать
unsigned char volatile* ocr_arr[] = { &OCR0A, &OCR0B };
*ocr_arr[0] = *ocr_arr[1] = 12;


Автор: technik-1017 Jul 8 2018, 19:37

если я не ошибаюсь, то каналы ШИМ в mega48 имеют разную разрядность, одни построены на 8-битном таймере, другие на 16-битном, вы же определяере все OCR как 8-битные

Автор: Ga_ry Jul 8 2018, 19:41

megajohn, спасибо, заработало!

Цитата(technik-1017 @ Jul 8 2018, 22:37) *
если я не ошибаюсь, то каналы ШИМ в mega48 имеют разную разрядность, одни построены на 8-битном таймере, другие на 16-битном, вы же определяере все OCR как 8-битные

Так в этом нет ничего страшного, регистры сравнения 8 битные и адреса их тоже.
Так что все нормально.
Нужно будет только выбрать для 16 битного таймера OCR1AL или OCR1AH

Автор: VladislavS Jul 9 2018, 03:21

Цитата(megajohn @ Jul 8 2018, 22:32) *
вот такой код в иаре компилится и должен работать
unsigned char volatile* ocr_arr[] = { &OCR0A, &OCR0B };
*ocr_arr[0] = *ocr_arr[1] = 12;
Какой-то у нас разный IAR. Тут ошибка. Адресное пространство неверно выбрано.
Цитата
Internal Error: [TaInstr::TaInstr]: Illegal instruction: 68 ( OUT 0x48, R16)


Тогда уж правильно вот так
Код
uint8_t volatile __io * const ocr_arr[] = {&OCR0A, &OCR0B };
*ocr_arr[0] = *ocr_arr[1] = 12;
=======================================

//   16 *ocr_arr[0] = *ocr_arr[1] = 12;  
        LDI     R16, 12
        OUT     0x28, R16
        OUT     0x27, R16


Не уверен что это будет работать, вот смотрите. Держу пари, вы не этого хотели.
Код
uint8_t volatile __io * ocr_arr[] = {&OCR0A, &OCR0B, &OCR1AL, &OCR1BL, &OCR2A, &OCR2B };
for(uint8_t i=0; i<6; i++)  *ocr_arr[i] = i;
=============================================================

        MOVW    R19:R18, R27:R26
        SBIW    R29:R28, 6
//   15 uint8_t volatile __io * ocr_arr[] = {&OCR0A, &OCR0B, &OCR1AL, &OCR1BL, &OCR2A, &OCR2B };
        MOVW    R17:R16, R29:R28
        LDI     R30, LOW(`?<Constant {(uint8_t volatile __io *)(&OCR0A),`)
        LDI     R31, (`?<Constant {(uint8_t volatile __io *)(&OCR0A),`) >> 8
        LDI     R20, 6
        LDI     R21, 0
        RCALL   ?ML_FLASH_SRAM_16EC_16_L07
//   16 for(uint8_t i=0; i<6; i++)  *ocr_arr[i] = i;
        LDI     R17, 0
        MOVW    R27:R26, R29:R28
        LDI     R16, 6
??main_0:
        LD      R30, X+
        LDI     R31, 0
        ST      Z, R17
        INC     R17
        DEC     R16
        BRNE    ??main_0


И вообще, зачем эти извращения? Если нужно записать шесть регистров, то проще и быстрее просто записать эти шесть регистров. Ну не десятки их в конце концов. Прочувствуйте разницу.
Код
OCR0A = 0; OCR0B = 1; OCR1AL = 2; OCR1BL = 3; OCR2A = 4; OCR2B = 5;
=================================================

        LDI     R16, 0
        OUT     0x27, R16
        LDI     R16, 1
        OUT     0x28, R16
        LDI     R16, 2
        STS     _A_OCR1A, R16
        LDI     R16, 3
        STS     _A_OCR1B, R16
        LDI     R16, 4
        STS     _A_OCR2A, R16
        LDI     R16, 5
        STS     _A_OCR2B, R16


PS: Хотя, если поиграться с расположением массива, то можно немного выиграть. Но всё равно, не торт. И 100% уверенности что записи попадут куда надо нет.
Код
static uint8_t volatile __io * const ocr_arr[] = {&OCR0A, &OCR0B, &OCR1AL, &OCR1BL, &OCR2A, &OCR2B };
for(uint8_t i=0; i<6; i++)  *ocr_arr[i] = i;

========================================
        LDI     R17, 0
        LDI     R26, LOW(??ocr_arr)
        LDI     R27, (??ocr_arr) >> 8
        LDI     R16, 6
        LDI     R31, 0
??main_0:
        LD      R30, X+
        ST      Z, R17
        INC     R17
        DEC     R16
        BRNE    ??main_0

Автор: Сергей Борщ Jul 9 2018, 07:29

QUOTE (VladislavS @ Jul 9 2018, 06:21) *
Какой-то у нас разный IAR. Тут ошибка. Адресное пространство неверно выбрано.
Да ладно! Весь ввод-вывод живет в том же адресном пространстве, что и ОЗУ. Если __io - это расширение для доступа командами IN/OUT, то не нужно через него пытаться лезть к OCR - потому что часть OCR просто не доступна через это адресное пространство.

Читайте внимательно текст ошибки: это внутренняя ошибка компилятора, то есть программисты что-то не предусмотрели внутри компилятора, надо сообщить им и ждать более новой версии.

Автор: VladislavS Jul 9 2018, 08:20

Цитата(Сергей Борщ @ Jul 9 2018, 10:29) *
Если __io - это расширение для доступа IN/OUT, то не нужно через него пытаться лезть к OCR - потому что часть OCR просто не доступна через это адресное пространство.

С __io компилятор сам разбирается где IN, а где STS использовать. Смотрите листинг. Без него, по идее, всё должно как ОЗУ трактоваться, но компилятор попытался OUT воткнуть и обломался.

Цитата(Сергей Борщ @ Jul 9 2018, 10:29) *
Читайте внимательно текст ошибки: это внутренняя ошибка компилятора, то есть программисты что-то не предусмотрели внутри компилятора, надо сообщить им и ждать более новой версии.
Версия последняя.

Автор: aiwa Jul 9 2018, 14:08

Цитата(VladislavS @ Jul 9 2018, 11:20) *
С __io компилятор сам разбирается где IN, а где STS использовать. Смотрите листинг. Без него, по идее, всё должно как ОЗУ трактоваться, но компилятор попытался OUT воткнуть и обломался.

Безусловно это внутренняя ошибка IAR. Даже листинг смотреть не стоит достаточно посмотреть на сообщение:
Illegal instruction: 68 ( OUT 0x48, R16)
IAR пытается оформить команду ввода-вывода OUT, но почему-то адрес операнда модифицирует для выполнения команды работы с памятью: 0x28 -> 0x48, поэтому и испытывает крайний внутренний дискомфорт. Правильная команда вывода должна быть OUT 0x28, R16.



Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)