Структуры на С для MK ?

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Опытный кот
Аватара пользователя
Сообщения: 703
Зарегистрирован: Вс янв 18, 2009 21:12:49

Сообщение asteroid7 »

Проще, типизировать указатель на функцию:

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

typedef float( * ptr_fun_t )( float );
Затем, массив из указателей объявить. Тут же и присвоить можно:

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

float cos(float);
float sin(float);
float tan(float);

ptr_fun_t ptr_fun_array[] = {
        cos,
        sin,
        tan,
};
Ну и обращаться к массиву

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

float y0 = ptr_fun_array[ 0 ]( 1 );
float y1 = ptr_fun_array[ 1 ]( 1 );
float y2 = ptr_fun_array[ 2 ]( 1 );
Есть один нюанс) В данном случае массив указателей в RAM находится. Так как это константы, то лучше во flash их разместить.
Реклама
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

Имхо, ТС хочет что-то такое

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

typedef float( * ptr_fun_t )( float );
ptr_fun_t ptr_fun_array[3][3];
Контактная информация:
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

urry писал(а):Имхо, ТС хочет что-то такое
этот ТС непонятно чего хочет - я ни одного из его вопросов на этом форуме (а их уже с десяток) так и не понял. умение задать вопрос - тоже искусство...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Опытный кот
Сообщения: 877
Зарегистрирован: Чт фев 18, 2010 13:51:56

Сообщение Murav »

FUZZY_ писал(а):как сделать вызов функций из funcarray_1
Как ни странно, обычным доступом к элементам массива:

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

pu[1][2] (10)
FUZZY_ писал(а):return array; - значения массива разрушаются при выходе из функции ???
Естественно разрушаются - сам массив то больше существовать не будет(он здесь - локальная переменная).
FUZZY_ писал(а):k=mfun;
Если хочешь вызвать функцию, то нужно не забывать () на конце.
Реклама
Эиком - электронные компоненты и радиодетали
Потрогал лапой паяльник
Сообщения: 390
Зарегистрирован: Чт сен 24, 2009 17:22:51
Откуда: UK

Сообщение FUZZY_ »

Спасибо.

Еще один вопросик о размещении переменных в памяти (RAM) - порядок следования, - откуда это можен узнать программа ?


размещение по указаному адресу как в EROM так в RAM например ,

разместить структуру с указаного адреса в RAM

разместить строку с указаного адреса ROM
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

FUZZY_ писал(а):Спасибо.
Еще один вопросик о размещении переменных в памяти (RAM) - порядок следования, - откуда это можен узнать программа ?
размещение по указаному адресу как в EROM так в RAM например ,
разместить структуру с указаного адреса в RAM
разместить строку с указаного адреса ROM
программа может узнать адрес любого объекта в ОЗУ при помощи оператора взятия адреса &, а вот для принудительного размещения объектов по ОЗУ существуют указатели (для динамического размещения) или особые фичи компилятора (для статического размещения в RОМ или EEPROM) - тут надо курить доку к конкретному компилятору, ибо стандарта на это нет
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Опытный кот
Аватара пользователя
Сообщения: 703
Зарегистрирован: Вс янв 18, 2009 21:12:49

Сообщение asteroid7 »

FUZZY_ писал(а):Еще один вопросик о размещении переменных в памяти (RAM) - порядок следования, - откуда это можен узнать программа ?
Для чего это надо?
Вы пишите на Си. Он для этого и предназначен, чтобы с размещением переменных и адресацией к ним не заморачиваться. Памяти под задуманное хватает или нет - весь вопрос.
Или имелось ввиду порядок следования байт больше байтовой переменной? Это от архитектуры зависит. В AVR - младший байт идёт первым.
Потрогал лапой паяльник
Сообщения: 390
Зарегистрирован: Чт сен 24, 2009 17:22:51
Откуда: UK

Сообщение FUZZY_ »

asteroid7 писал(а):
FUZZY_ писал(а):Еще один вопросик о размещении переменных в памяти (RAM) - порядок следования, - откуда это можен узнать программа ?
Для чего это надо?
Вы пишите на Си. Он для этого и предназначен, чтобы с размещением переменных и адресацией к ним не заморачиваться.
Например вставить строку о версии прошивки в конце ROMа как в старых BIOSах
Uchar ver[]="ROM ver 1.1.0 12\12\10 CS 1FDF" или что-то подобное.
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

В МСС я бы взял скрипт линкера, ограничил максимально доступную память компилятора на эту выделенную область, обозвал ее как- нибудь и дальше в программе через директиву pragma ввел туда время через переменную TIME
От компилятора зависит.
Контактная информация:
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

FUZZY_ писал(а):Например вставить строку о версии прошивки в конце ROMа как в старых BIOSах
Uchar ver[]="ROM ver 1.1.0 12\12\10 CS 1FDF" или что-то подобное.
в GCC для этого служат секции:

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

Uchar __attribute__((section(".my_section"))) ver[] = "что-то там";
а затем в опциях компилятора указывается требуемый адрес секции .my_section, и линкер сам кладет данные по этому адресу.

можно и как urry сказал - скриптом линкера...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 703
Зарегистрирован: Вс янв 18, 2009 21:12:49

Сообщение asteroid7 »

Слышал, что "@ ADDRESS" в некоторых компиляторах работает. В IAR точно.
Структура с постоянного адреса 0x200 во flash для IAR.

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

__root __flash struct {
    //формат: Mmm dd yyyy\0 hh:mm:ss\0
    U8 date[ sizeof( __DATE__ ) ];
    U8 time[ sizeof( __TIME__ ) ];
    //имя файла с main() \0
    U8 file[ sizeof( __FILE__ ) ];
} F_DeviceHeader @ 0x200 = { __DATE__, __TIME__, __FILE__ };
Потрогал лапой паяльник
Сообщения: 390
Зарегистрирован: Чт сен 24, 2009 17:22:51
Откуда: UK

Сообщение FUZZY_ »

Спасибо принцип понял.

Еще вопросик по вложености структур, приведение типов

//-------------------------------------------------
typedef char ( * callfunc)( char, char )
//------------------------------------------------
typedef struct a1
{
char * p1;
callfunc func1;
unsigned int *adr;
};
//-------------------------------------------------

struct all {
char *p1;
a1 s1;
unsigned int *adr;
};
//-------------------------------------------------
char Add(char s,char ss)
{
return (s+ss); //переполнение не важно
}
//------------------------------------------------

void main(void)
{
char x=y=10;

all mystruct; //создаем mystruct

mystruct.funct1=&Add; // заполнение поля

mystruct.p1=mystruct.s1.funct1(x,y); // сохраняем в p1 результат выполнения - ???

mystruct.adr=&mystruct.s1; // получить адрес начала структуры s1 - ???

}
Прошу исправить ошибки
Последний раз редактировалось FUZZY_ Сб сен 11, 2010 18:01:32, всего редактировалось 1 раз.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

FUZZY_ писал(а):Прошу исправить ошибки
может, лучше литературу изучить наконец по языку Си?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

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

Сообщение avreal »

«Извените за многа букаф»
Murav писал(а):Имя функции - это только имя функции и указателем оно само по себе не является. Как раз более правильная запись получения указателя на функцию - использование &. Кстати вызывать функцию через указатель, в отличие от имени, можно с разыменовыванием (*funcptr)() , но естественно никто так не пишет.
На мой взгляд, всё-таки имя функции ближе к имени массива - само по себе уже является указателем. И никакого "в отичие от имени".
Немного цитат из стандарта С99 (в С89 то же самое, но в 99 местами подробнее расписано).

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

6.9.1 Function definitions
...
EXAMPLE 2
To pass one function to another, one might say
int f(void);
/* ... */
g(f);

Then the definition of g might read

void g(int (*funcp)(void))
{
    /* ... */
    (*funcp)() /* or funcp() ... */
}
or, equivalently,
void g(int func(void))
{
    /* ... */
    func() /* or (*func)() ... */
}
Обратите внимание - в примере из стандарта вызове функции g(f) нет взятия адреса &, в этом нет смысла (хотя и можно сделать), так как:
6.3.2 Other operands
6.3.2.1 Lvalues, arrays, and function designators
...
4 A function designator is an expression that has function type. Except when it is the operand of the sizeof operator or the unary & operator, a function designator with type ‘‘function returning type’’ is converted to an expression that has type ‘‘pointer to function returning type’’.
Было бы применение & «более правильным» - поставили бы в примере его. А так просто для & сделали исключение и в случае его применения не делают автоматического преобразования (а для sizeof сделали исключение, чтобы неповадно было размер фунции брать - поскольку автопреобразования нет, под sizeof попадает не указатель, у которого есть размер, а «непонятно что наравне с неполным типом» и получается ошибка времени компиляции). Т.е. фактически везде, где применяется имяфункции - оно рассматривается как указатель на неё (ещё об этом ниже в цитате из 6.5.2.2 Function calls).
Оба определения функции g() эквивалентны. Во втором в качестве параметра выступает не указатель на функцию, а функция (как и в случае массива - параметром можно указать массив и в теле обращаться как к массиву, реально передаётся указатель и для функции тоже). При этом во втром варианте, точно так же, как и в первом, можно использовать оба варианта вызова - и просто с именем, и с разименованием.
Собственно,

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

#include <avr/io.h>

uint8_t foo(uint8_t a);

void moo()
{
        PORTB = foo(1);
        PORTB = (*foo)(2);
}
/usr/bin/avr-gcc -std=c89 --pedantic -Os -S -mmcu=atmega8 funcptr.c

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

.global	moo
	.type	moo, @function
moo:
	ldi r24,lo8(1)
	rcall foo
	out 56-32,r24
	ldi r24,lo8(2)
	rcall foo
	out 56-32,r24
	ret
Ещё
6.5.2.2 Function calls
Constraints
1 The expression that denotes the called function 77) shall have type pointer to function returning void or returning an object type other than an array type.
...
Semantics
3 A postfix expression followed by parentheses () containing a possibly empty, comma-separated list of expressions is a function call. The postfix expression denotes the called function. The list of expressions specifies the arguments to the function.
...
77) Most often, this is the result of converting an identifier that is a function designator.
Т.е. любой вызов функции - это работа с указателем на функцию, который, согласно сноске 77, "чаще всего получается в качестве преобразования идентификатора, являющегося обозначением функции"
И вообще, этот параграф 6.5.2.2 есть часть раздела
6.5.2 Postfix operators
Syntax
postfix-expression:
primary-expression
postfix-expression [ expression ]
postfix-expression ( argument-expression-list opt )
postfix-expression . identifier
postfix-expression -> identifier
postfix-expression ++
postfix-expression --
( type-name ) { initializer-list }
( type-name ) { initializer-list , }
Выделенное - это и есть вызов функции. Т.е. любой вызов функции - это выражение с постфиксным оператором ( ), внутри которого могут опционально быть аргументы функции.
Кстати, довольно свободное обращение с именами функций было уже в Алголе-68 (да, да, я часто это цитирую, но оно мне нравится)

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

a := if x > 0 then sin else cos fi (x);
в C-шном эквиваленте

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

a = (x > 0 ? sin : cos)(x);
Ну и совсем ради хохмы
#include <avr/io.h>

uint8_t foo(uint8_t a);

void moo()
{
PORTB = (****foo)(2);
}
Точно так же прекрасно компилируется в простой вызов. Уже давно под рукой ничего, кроме gcc нет (хотя с --pedantic он ругается на несоответсвия стандарту), но это как бы не в Borland C 3.1 тоже компилировалось. Я это понимаю так
6.5.3.2 Address and indirection operators
...
4 The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; ...
foo - function designator
согласно 6.3.2.1 моментально превращается в pointer to function
согласно 6.5.3.2 при помощи самой правой звёздочки превращается назад в function designator
но стоит в выражении и согласно 6.3.2.1 ... далее по тексту, но уже со следующей звёздочкой.


p.s. антиоффтоп: согласен с ARV по поводу того, что раз уж захотелось в структуре указателей на функции в таком количестве, то стоит подумать о явном приенении С++ вместо его ручной эмуляции.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Потрогал лапой паяльник
Сообщения: 390
Зарегистрирован: Чт сен 24, 2009 17:22:51
Откуда: UK

Сообщение FUZZY_ »

Спасибо за детальное обяснение.

Вопрос я думаю в эту тему . Перемещаемая функция - есть участок кода с Adr_begin до Adr_end при копировании копировании которого его работа не нарушается. На пратике выглядит так :

bin редактором копируем участок кода в свободное пространство EEPROM - затем в программе на С вызываем
ee.

Функцию вставили с адреса 0xEFFF или другого подходящего адреса

typedef int ( * FUNC)(char,char);

typedef void (*FREE)(char,char);

FUNC MyCall;

FREE MyFree;
void main(void)

{
int rezult;
char k;

MyCall=(int( *)(char, char) )0xEFFF; // правильно ли я сделал преобразование типов

MyFree=(void ( *)(char, char) )0xEFFF;

rezult=MyCall(10,20);

k=(char) ( MyFree(10,20) ); // Lo byte Int

printf(" rezult=%d, Lo Byte=%d",rezult, (int) k);
}

На асм как писать перемещаемую функцию я знаю, как это реализовать на С?
Опытный кот
Сообщения: 877
Зарегистрирован: Чт фев 18, 2010 13:51:56

Сообщение Murav »

Лучше для запуска кода из оперативной памяти при компиляции указать компилятору, что этот код будет находится в оперативной памяти, а сам код хранить в памяти прошивки и при запуске загружать в память на нужное место. А после этого вызывать его как обычные статические функции.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

а мне вот интересно: о какой платформе тут идет речь? по-моему, "привычные" для форумчан МК не имеют возможности работать с перемещаемыми функциями... сдается мне, речь об ARM?

уж не знаю, как там в ARM все устроено, но в принципе компилятор может сгенерировать функцию с использованием переходов по абсолютным адресам, и тогда перемещать ее в произволдьное место будет далеко не тривиальным! загрузчик даже во времена MS DOS для 80х86 процессоров был не таким уж простым, что потребовало особого формата файлов EXE, в отличие от COM, которые грузились всегда по одному и тому же абсолютному адресу (в пределах сегмента, естественно).
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Потрогал лапой паяльник
Сообщения: 390
Зарегистрирован: Чт сен 24, 2009 17:22:51
Откуда: UK

Сообщение FUZZY_ »

[quote="ARV"]а мне вот интересно: о какой платформе тут идет речь? по-моему, "привычные" для форумчан МК не имеют возможности работать с перемещаемыми функциями... сдается мне, речь об ARM?


Плату приобрел на барахолке от DVD цепляю туда свою плату на рисунке приблизительно то что есть.

RAM общее для 2 процов (ALI , MCS) Гружу свои параметры в память дальше идет выполнение штатным процессором,
затем его работу останавливаю и беру резльтат .
Вложения
RIS.JPG
(49.47 КБ) 328 скачиваний
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

понятненько... реверс-инжиниринг делаете? ;)
так вот я пока не понял, в чем проблема с "перемещением" функций: у MCS51 семейства по идее обмануть МК и подсунуть ему коды не из его собственного ПЗУ, а из внешнего (хоть ОЗУ, хоть ПЗУ) можно чисто аппаратно... хотя в МК фирмы Atmel (думаю, и у других производителей так же) от подобного "лома" встроен "прием": можно заблокировать эту фичу... видимо, с этим и боретесь? ;)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Потрогал лапой паяльник
Сообщения: 390
Зарегистрирован: Чт сен 24, 2009 17:22:51
Откуда: UK

Сообщение FUZZY_ »

Проблема старта функции с указаного адреса. Че-то я с механизмом на С не все догоняю.

(Не к теме.
Ради шутки делали послойное сремблирование Atmel на оборудовании не так уж сложно снять биты защиты.
Atmel на топологии кристалла экономит... А таким способом китайцы и все взламывают )
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»