Проблема с полями структур (IAR)

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Держит паяльник хвостом
Аватара пользователя
Сообщения: 958
Зарегистрирован: Вс дек 02, 2012 16:58:33
Откуда: от туда

Сообщение GARMIN »

Попробую задать этот вопрос и здесь, может кто сможет подсказать.
Процессор STM32F051. Среда IAR.
Преамбула.
Я написал драйвер TFT экрана и использую FreeRTOS 7.3
Для того, чтобы отделить задачу драйвера от других задач, использую очередь.
В очереди передаю указатель на буфер данных для дисплея.
Когда передавал только текст, было всё хорошо. Но понадобилось передавать команды управления.
Задумка простая: первый байт - длина данных или текста (int8_t) - знаковое число, потом сама команда. Если длина данных положительная, то это текстовая строка. Если отрицательная - это команда. Команды бывают с параметрами, например установка позиции курсора. Для простого доступа к отдельным полям я определил структуры управления:

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

typedef struct          // структура указателей на буфер для передачи через очередь
{
uint16_t   size;       // размер данных
uint8_t    *buffer;   // указатель на буфер
} IO_BUF;

typedef struct
{
   int8_t      len;
   TFT_COMAND   command;
   uint16_t x;
   uint16_t y;
} TFT_S_CURSOR;
Теперь я присваиваю указателю на структуру TFT_S_CURSOR адрес буфера и заполняю буфер как структуру:

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

   TFT_S_CURSOR *p_cursor = (TFT_S_CURSOR *)&g.TFT_out.buffer[index];
   p_cursor->len = -(int8_t)sizeof(TFT_S_CURSOR);
   p_cursor->command = C_CURSOR;
   p_cursor->x = 10U;
   p_cursor->y = 20U;
   index += sizeof(TFT_S_CURSOR);
где g.TFT_out.buffer - это массив типа uint8_t
а index - смещение от начала буфера, так как в одном буфере могут передаваться несколько команд.
Сама структура g выровненная по полю 4 байта.
команда command типа enum, то есть размера char
В момент присвоения p_cursor->x = 10; возникает hard fault error

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

Сообщение ARV »

я бы сделал union-ом структуру, охватывающую все варианты команд с соответствующими полями, и вместо uint8_t *buffer использовал бы указатель на эту структуру...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Держит паяльник хвостом
Аватара пользователя
Сообщения: 958
Зарегистрирован: Вс дек 02, 2012 16:58:33
Откуда: от туда

Сообщение GARMIN »

union это хорошая идея. Но она не решает двух вопросов.
1) сам hard fault при присвоении данных.
2) несколько команд в одном буфере.
Контактная информация:
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

я не вижу весь текст и не понимаю -если это динамическое выделение - где нью иди аллоки ?

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

#ifndef __bufers_H__
#define __bufers_H__ 
//работа с кольцевым буфером 
//состояние буфера - перечисление всех возможных ответов
typedef enum {BUFER_OK=0,/*команда удачно положена или извлечена из буфера*/\
BUFER_BUSY,/*буфер переполнен (для функции - добавить)*/\
BUFER_EMPTY/*буфер пустой, команда не принята (для функции - взять)*/\
}REZ_BUFER;
//--------------------------------------------------------------------------
typedef struct
{
   unsigned char      len;
   unsigned char   command;
   unsigned int x;
   unsigned int y;
} TFT_S_CURSOR;

// 
extern volatile TFT_S_CURSOR tft_cursor;
//
extern REZ_BUFER fnAddStruct(void);
extern REZ_BUFER fnGetStruct(void);


#endif //__bufers_H__
//------------------------------------------

// bufer.c
#define BUF_COM_SIZE 30

volatile TFT_S_CURSOR tft_cursor;
struct
{
	TFT_S_CURSOR sBufStr[BUF_COM_SIZE];
	unsigned char cRead;
	unsigned char cWrite;
}strBuff;

void fnBuferInit(void)
{
	strBuff.cRead=strBuff.cWrite=0;
}
//--------------------------------------------------------------------
REZ_BUFER fnAddStruct(void)
{
	strBuff.sBufStr[strBuff.cWrite].len=tft_cursor.len;
	strBuff.sBufStr[strBuff.cWrite].command=tft_cursor.command;
	strBuff.sBufStr[strBuff.cWrite].x=tft_cursor.x;
	strBuff.sBufStr[strBuff.cWrite].y=tft_cursor.y;

	strBuff.cWrite++;
	if(strBuff.cWrite == strBuff.cRead){return BUFER_BUSY;}
	if(strBuff.cWrite >= BUF_COM_SIZE){strBuff.cWrite=0;}
	return BUFER_OK;

}
//--------------------------------------------------------------------
REZ_BUFER fnGetStruct(void)
{
	if(strBuff.cWrite == strBuff.cRead){return BUFER_EMPTY;}
	tft_cursor.len=strBuff.sBufStr[strBuff.cRead].len;
	tft_cursor.command=strBuff.sBufStr[strBuff.cRead].command;
	tft_cursor.x=strBuff.sBufStr[strBuff.cRead].x;
	tft_cursor.y=strBuff.sBufStr[strBuff.cRead].y;
	strBuff.cRead++;
	if(strBuff.cRead >= BUF_COM_SIZE){strBuff.cRead=0;}
	return BUFER_OK;	
}
//--------------------------------------------------------------------

Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Держит паяльник хвостом
Аватара пользователя
Сообщения: 958
Зарегистрирован: Вс дек 02, 2012 16:58:33
Откуда: от туда

Сообщение GARMIN »

Ну это же embedded с :)
Менеджер памяти тут отсутствует
Структура g статическая и доступна из любого места программы. Указатель динамический, ему отдельной памяти не надо.

Спасибо за помощь. Прочитал программу. Вы передаёте указатели на структуры.

У меня несколько другой подход. Я хочу передавать драйверу указатель на структуру IO_BUF в любом случае. А в буфере структуры должны быть либо текст, либо команды.

Для текстового дисплея я это сделал. Только там применил спецсимволы \n, \t и т.д.
Хотел бы оставить единый программный интерфейс для всех драйверов.
Контактная информация:
Реклама
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

GARMIN писал(а):Теперь я присваиваю указателю на структуру TFT_S_CURSOR адрес буфера и заполняю буфер как структуру:
Непонятно сие извращение. Для чего это, если можно работать напрямую со структурами, без всяких дополнительных буферов и указателей на них ?
ИМХО, затея не из хороших. А если буфер переполнится (окажется размером меньше) ? И будете Вы тогда писать "в никуда"... Или ошибётесь и при приведении укажете куда-нибудь не туда... Что, вероятней всего, и происходит.
Не зря Страуструп в плюсах сделал явное приведение через заднее место с кучей геморроя... :))
GARMIN писал(а):так как в одном буфере могут передаваться несколько команд
Дак создайте массив этих структур и передавайте его через указатель с кол-вом актуальных структур. И будет Вам сколько угодно команд... А при обработке достаточно одного инкремента указателя для перехода к следующей структуре, компилятор сам все адреса вычислит, без всяких заморочек типа sizeof и передачей этого размера (в Вашем случая - поле "len").
GARMIN писал(а):Ну это же embedded с
Ну и что. В "C" аллоки ещё никто не отменял :)
И в Вашем случае их тоже можно применить. Создали массив структур-команд в куче, заполнили их, передали, выгрузили.

ЗЫ: Забейте на явное приведение, ни к чему хорошему оно не приводит. А в Вашем случае вообще можно спокойно без него обойтись.
Реклама
Держит паяльник хвостом
Аватара пользователя
Сообщения: 958
Зарегистрирован: Вс дек 02, 2012 16:58:33
Откуда: от туда

Сообщение GARMIN »

Аlex писал(а):
GARMIN писал(а):Теперь я присваиваю указателю на структуру TFT_S_CURSOR адрес буфера и заполняю буфер как структуру:
Непонятно сие извращение. Для чего это, если можно работать напрямую со структурами, без всяких дополнительных буферов и указателей на них ?
Во - первых, это нужно для безопасности. Чтобы не напутать, где какая переменная и в каком виде лежит.
Во - вторых, так гораздо читабельнее код. Я завернул работу со структурами в обёртку из макросов с параметрами и заполнение буфера командой получается из одной строчки кода.
Аlex писал(а): А если буфер переполнится? И будете Вы тогда писать "в никуда"...
Проблема с адресацией массива в самом си. Я до этого не дошёл, споткнулся раньше.
Аlex писал(а): Дак создайте массив этих структур и передавайте его через указатель с кол-вом актуальных структур.
Идея красивая, но мне придётся передавать большой массив, содержащий все возможные команды, так как команды разного размера и структуры. Плюс массив текстового буфера. Для маленького процессора это расточительно.
Аlex писал(а):И в Вашем случае их тоже можно применить. Создали массив структур-команд в куче, заполнили их, передали, выгрузили.
Надо подумать, я пока не использовал динамически выделяемую память. Сколько места займёт менеджер памяти, не знаю.
Контактная информация:
Держит паяльник хвостом
Аватара пользователя
Сообщения: 958
Зарегистрирован: Вс дек 02, 2012 16:58:33
Откуда: от туда

Сообщение GARMIN »

Проблема решена. Использовал union для описания расположения нескольких команд в одной области памяти и очередь для хранения нескольких команд до их выполнения.
Благодарю.
Контактная информация:
Ответить

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