Как Сделать Чтобы Массив Начинался С Ячейки 001001 (Для Си)?

Обсуждаем контроллеры компании Atmel.
Ответить
Встал на лапы
Сообщения: 103
Зарегистрирован: Чт мар 08, 2012 01:13:30

Сообщение astrgan »

Как сделать чтобы массив начинался с ячейки 001001?
На Ассемблере была директива .org (если не перепутал), как сделать такое на Си?

Хочу использовать полученный через порт байт как указатель на элемент массива.

Код: Выделить всё

char *p[]={msi+0, msi+8,    msi+16,    msi+24,    msi+32,    msi+40,    msi+48,    msi+56,    msi+64,    msi+72};
P.S. мк - avr; компилятор winavr(тот что с avrstudio идет)
Реклама
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

А почему не использвать принятый байт как индекс? Ну, при необходимости приведя к нужному диапазону.
Скажем, посылая символы от '0' до '9' хочется выбирать элементы массива с номерами от 0 до 9 -- проверить на диапазон и вычесть '0'

Код: Выделить всё

    char ch = uart_getchar();
    if (ch < '0' || ch > '9') {
        // обработать ошибку
    } else {
        // что-то сделать с    array [ ch - '0' ] 
    }
Если на С начинает хотеться разметсить переменную по конкретному физическому адресу, то в подавляющем большинстве случаев это значит, что на С пишется асм-программа. асм-программы лучше на асме и писать.

Обдумайте заново, что хочется сделать, для этой задачи врядли нужно иметь переменную по конкретному абсолютному адресу.

В GCC можно создать отдельную секцию данных, которую линкерным ключиком или скриптом разместить там, где хочется. Но там начнутся проблемы с её инициализацией, если это не константный массив во флеше. Придётся доп. код писать.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Реклама
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

Вдогонку -- тут в этом примере всё равно с точки зрения правильности кода, так как и диапазон кодов '0'…'9', и диапазон 0…9 влазят в диапазон 0…127. Поэтому всё будет корректно работать независимо от «знаковости» char

Но лучше на это не рассчитывать и выбирать unsigned char / signed char или там uint8_t / int8_t в зависимости от реальных потребностей.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

И тем не менее.....

AVReal, пораскинь ка, неужели нет возможности как то задать привязку, например структуры, к определенному адресу (можно конечно и при компиляции узнать адрес, куда легла структура, но это как-то не то.....)

Задача такая (я все никак не угомонюсь), надо основную прогу написать на C (быстро, гибко, удобно, наглядно.....),
а обработчик прерываний на АСМЕ (оптимальность кода, скорость - под сотню килогерц можно заталяпать). Обычно обработчик прерывания намного меньше основной проги, так что АСМ напрягать не должен (тем более мне нравится писать на асме). Как мне кажется, такой симбиоз, это просто бомба будет.

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

Т.е. в C работаем как с обычной структурой (наверное надо объявить ее как volatile), а из ассемблерной вставки, работаем с массивом начинающимся с известного адреса..... Вот так через C-структуру\ASM-массив и будут сотрудничать C и АСМ.

Я тут уже не первый раз пытаюсь воду мутить насчет этого, но чет пока, никто не поддержал .....
Толи это бредовая идея, толи таких задач нет ни у кого..... Но у меня есть реальная потребность соединить основную прогу на C и обработчик прерывания на АСМ-е

(можете считать это моим капризом - хочу иконки на рабочем столе..... хочу иконки.....)



Ой.....
Написал, только потом рассмотрел про отдельную секцию
Надо покумекать.....
Реклама
Эиком - электронные компоненты и радиодетали
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

выделить в проекте место под переменные, которые не будет трогать компилятор, дать этой секции название, чтобы ее понял линкер линкеру это объяснить - все эти телодвижения должны быть как-то объяснены. Ну смысл задавать адрес массиву, если его можно и так узнать ???
Единственный раз, когда это мне нужно было делать - это нужно было объединять банки ОЗУ в 1 массив экрана для 18 пика. Все.
shads, какие регистры выделяются для асмовых вставок в винавр - это уже было и на коте и, тем более, в документации...
Контактная информация:
Реклама
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

shads писал(а):Задача такая (я все никак не угомонюсь), надо основную прогу написать на C (...), а обработчик прерываний на АСМЕ (...).

На C пишем так чтобы на определенный заданный адрес легла структура
...
Т.е. в C работаем как с обычной структурой (наверное надо объявить ее как volatile),
а из ассемблерной вставки, работаем с массивом начинающимся с известного адреса.....
Вот так через C-структуру\ASM-массив и будут сотрудничать C и АСМ.

Надо покумекать.....
Всё покумекано до нас.
Основной модуль на С:
Спойлер

Код: Выделить всё

#include <avr/io.h>
#include <avr/interrupt.h> // sei()

typedef struct {
        uint8_t a;
        uint8_t b;
} some_struct_t;

volatile some_struct_t some_struct; // Просто определяем экземпляр структуры.

int main()
{
        TCCR0  = (1 << CS01) | (1 << CS00);
        TIMSK |= (1 << TOIE0);
        sei();
        for (;;) {
                some_struct.a = 10;
                while (some_struct.a) ;
                PORTB = some_struct.b;
        }
} 
Обработчик прерывания на асме
Спойлер

Код: Выделить всё

.nolist // это чтобы листинг покороче был
#define __SFR_OFFSET 0 // это чтобы не писать _SFR_IO_ADDR(PORTB)
#include <avr/io.h>
.list
// Описываем смещения полей С-шной структуры. Изменения нужно вносить синхронно
// с С-шным файлом, где-то на электрониксе кто-то выкладывал своё на тему
// автоматической трансляции этого дела от С-шного h-файла для асма.
        .struct 0
s_a:    .skip 1 // они по одному байту
s_b:    .skip 1

        // Говорим, что где-то существует какой-то объект с именем some_struct
        // При писании всего проекта на асме, но в нескольких файлах то же самое делали бы
        .global some_struct

        .text
        .global TIMER0_OVF_vect
TIMER0_OVF_vect:
        push    r16
        in      r16, SREG
        push    r16
        lds     r16, some_struct + s_a // обращаемся к полю по смещению
        tst     r16
        brne 1f
        dec     r16
        sts     some_struct + s_a, r16
        in      r16, PINC
        sts     some_struct + s_b, r16
1:
        pop     r16
        out     SREG, r16
        pop     r16
        reti

        .end
Собираем, тут я прямо одной строкой для примера, а не через проект

Код: Выделить всё

avr-gcc -O2 -mmcu=atmega8 -ggdb -Wa,--gstabs -o tst.elf tst_c.c tst_asm.S
avr-objdump -DS tst.elf >tst.dump
Выдача дизассемблера:
Спойлер

Код: Выделить всё

Disassembly of section .text:

00000000 <__vectors>:
   0:   12 c0           rjmp    .+36            ; 0x26 <__ctors_end>
   2:   2c c0           rjmp    .+88            ; 0x5c <__bad_interrupt>
   4:   2b c0           rjmp    .+86            ; 0x5c <__bad_interrupt>
   6:   2a c0           rjmp    .+84            ; 0x5c <__bad_interrupt>
   8:   29 c0           rjmp    .+82            ; 0x5c <__bad_interrupt>
   a:   28 c0           rjmp    .+80            ; 0x5c <__bad_interrupt>
   c:   27 c0           rjmp    .+78            ; 0x5c <__bad_interrupt>
   e:   26 c0           rjmp    .+76            ; 0x5c <__bad_interrupt>
  10:   25 c0           rjmp    .+74            ; 0x5c <__bad_interrupt>
  12:   36 c0           rjmp    .+108           ; 0x80 <__vector_9>
  14:   23 c0           rjmp    .+70            ; 0x5c <__bad_interrupt>
... пропускаем кучу неинтересного
0000005e <main>:

volatile some_struct_t some_struct;

int main()
{
        TCCR0  = (1 << CS01) | (1 << CS00);
  5e:   83 e0           ldi     r24, 0x03       ; 3
  60:   83 bf           out     0x33, r24       ; 51
        TIMSK |= (1 << TOIE0);
  62:   89 b7           in      r24, 0x39       ; 57
  64:   81 60           ori     r24, 0x01       ; 1
  66:   89 bf           out     0x39, r24       ; 57
        sei();
  68:   78 94           sei
        for (;;) {
                some_struct.a = 10;
  6a:   9a e0           ldi     r25, 0x0A       ; 10
  6c:   90 93 60 00     sts     0x0060, r25
                while (some_struct.a) ;
  70:   80 91 60 00     lds     r24, 0x0060
  74:   88 23           and     r24, r24
  76:   e1 f7           brne    .-8             ; 0x70 <main+0x12>
                PORTB = some_struct.b;
  78:   80 91 61 00     lds     r24, 0x0061 ; <--- обращение к полю b
  7c:   88 bb           out     0x18, r24       ; 24
  7e:   f6 cf           rjmp    .-20            ; 0x6c <main+0xe>

00000080 <__vector_9>:
        .global some_struct

        .text
        .global TIMER0_OVF_vect
TIMER0_OVF_vect:
        push    r16
  80:   0f 93           push    r16
        in      r16, SREG
  82:   0f b7           in      r16, 0x3f       ; 63
        push    r16
  84:   0f 93           push    r16
        lds     r16, some_struct + s_a
  86:   00 91 60 00     lds     r16, 0x0060
        tst     r16
  8a:   00 23           and     r16, r16
        brne 1f
  8c:   31 f4           brne    .+12            ; 0x9a <__vector_9+0x1a>
        dec     r16
  8e:   0a 95           dec     r16
        sts     some_struct + s_a, r16
  90:   00 93 60 00     sts     0x0060, r16
        in      r16, PINC
  94:   03 b3           in      r16, 0x13       ; 19
        sts     some_struct + s_b, r16 
  96:   00 93 61 00     sts     0x0061, r16   ; <--- и тут обращение к полю b
1:
        pop     r16
  9a:   0f 91           pop     r16
        out     SREG, r16
  9c:   0f bf           out     0x3f, r16       ; 63
        pop     r16
  9e:   0f 91           pop     r16
        reti
  a0:   18 95           reti
Так что таки желание разместить что-то по фиксированному адресу должно быть очень хорошо аргументировано.
У меня есть такое в одном месте — блок конфигурационных данных во флеше, который стенд-программатор приклеивает к рабочей прошивке после того, как обработал данные от тестово-калибровочной прошивки. Ну так вот чтобы стенд всегда работал с одними и теми же адресами при незначительных (не затрагивающих формат конфиг-блока) изменениях рабочей программы, эта структура прибита на фиксированное место во флеше.
Кстати, именно та программа на ассемблере :-)
Но всё равно сделано через секцию и линкер, а не через .org
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Реклама
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Вооо..... то что надо. Спасибочки.....

Правда вопросов куча будет..... Как я понял и С и АСМ в одном проекте набраны?
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

Да, их нужно включить в один проект.
Думаю, и в студии проблем не должно быть.
У меня болванка makefile проекта включает в себя avr-gcc.mak, который от основного Makefile получает список каталогов проекта («модулей») и подхватывает оттуда все имеющиеся там .c, .cpp, .S
Как под досом ещё было, так и сейчас в Code::Blocks.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Ну тады все упрощается..... (относительно..... т.к. я не знаю как в AVRStudio, в одном проекте, объединить C и ASM.....)
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

посмотри проект чена http://elm-chan.org/works/akilcd/report_e.html
там вставка на вставке сидит и вставкой погоняет :)
Контактная информация:
Ответить

Вернуться в «AVR»