реклама на сайте
подробности

 
 
2 страниц V  < 1 2  
Reply to this topicStart new topic
> Как заставить помещать строки во флэш?
andrvisht
сообщение Nov 3 2006, 13:02
Сообщение #16


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



Попробовал сделать так
в опциях добавил --string_literals_in_flash
написал функцию типа
Код
foo(char __flash *s)
{
  while (*s++ != 0)
  {
    PORTA = *s;
  }
}

при вызове сделал так
Код
foo((char __flash*)"MyFlash");


вроде как из Flash берет, проверьте, может подойдет ...
Go to the top of the page
 
+Quote Post
sKWO
сообщение Mar 9 2008, 10:33
Сообщение #17


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Добрый всем день! Народ подыму старую тему.
Люди, подскажите, что я делаю не так? переписываю драйвер для ГЖКИ 128х64 с винавра на иар
ИАР для АВР версия 4.21А.
пишу:
Код
#include <pgmspace.h>
....
//основная функция
int main(void) {
               ...
               ...
    LoadBitmap(IMAGE);//////////// ОШИБКА Error[Pe167]
    
}
// функция для загрузки карты
void LoadBitmap(unsigned char *bitmap)
{
  
uint16_t i, j,by;
for(i=0; i<64; i+=8)

        for(j=0; j<128; j++)
        {
            by = printf_P(bitmap++); /////////// ОШИБКА Error[Pe167]
            ks0108GotoXY(j, i);
            ks0108WriteData(by);
        }
}
// и сама карта (массив)
#define LCD_WIDTH 128
const __flash uint8_t IMAGE[] = {
.....
.....
    };

void LoadBitmap(uint8_t *bitmap);

Ну и соответственно и еррор:
Error[Pe167]: argument of type "unsigned char const __flash *" is incompatible with parameter of type "uint8_t *"

В общем на форуме видел сходную ветку : Как заставить помещать строки во флэш
созданную Протоссом, соответственно в опциях проекта в закладке "C compiler" -> "Extra Options"
поставил птицу "Use command line options" и набрал строчку --string_literals_in_flash
НИЧЕГО. В общем IgorKossak знает ответ но чего-то помоему недоговаривает.

Вобщем то ключевые слова signed и unsigned обычно применяются к обьектам, содержащим по смыслу числовые значения.
Что же касается символьных обьектов и строк на их основе, то общепринятым типом в этом случае является просто char.
Поэтому и обьявления в pgmspace.h вполне оправданные и корректные.
Я НХ не понял!!чёто туго
Решил проблему частично так, создал следующую функцию по совету &-rey :
Код
FuncFlash(char __flash *str_)
{
  while (*str_++ != 0);
}

ну и соответственно ее вызов для чтения массива в памяти программ
by = FuncFlash((char __flash*)(bitmap++));

Но с использованием стандартных функций ИАР темно.
теперь выдаёт только одну туже ошибку на LoadBitmap(IMAGE);//////////// ОШИБКА Error[Pe167]
Error[Pe167]: argument of type "char const __flash *" is incompatible with parameter of type "char __flash **"
в общем прикреплю файлы, может кто поможет ? это не горит. Буду признателен по любой информации загрузки (выдачи) массива данных из памяти программ по определённому алгоритму.
Спасибо.
Прикрепленные файлы
Прикрепленный файл  ks0108.zip ( 58.28 килобайт ) Кол-во скачиваний: 28
 


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 9 2008, 12:33
Сообщение #18


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Вы запутались в указателях.
char * - указатель на char
char const * - указатель на константный char.
"Обычный" язык С не знает ничего о флеш, для него cont - всего лишь указание, что данные read-only.
Через указатель на константные данные вы их можете читать. Через обычный указатель - читать и писать. Поэтому вы можете свободно присвоить неконстантный указатель константному - тем самым вы лишь ограничиваете доступ к данным. А вот обратное присвоение запрещено - ибо таким образом вы могли бы полуучить доступ на запись к данным read-only (на самом деле такое присвоение возможно, но лишь с явным приведением типов и оно целиком на совести программиста). Вот компилятор в вашем случае и ругается - вы пытаетесь при помощи указателя получить доступ на запись к константному объекту.
Вам надо прототип функции объявить как FuncFlash(char const __flash *str_), ибо массив, который вы пытаетесь ей передать - константный (const __flash uint8_t IMAGE[] = ....)


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
sKWO
сообщение Mar 9 2008, 17:44
Сообщение #19


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



В общем огромнейшее спасибо Вам, Сергей Борщ!!!!!!!!!
Получилось так:
в хедере Bitmap.h массив карты const __flash char IMAGE[];
в Bitmap.с написал так
Код
FuncFlash(char __flash *str_)
{
  while (*str_++ != 0);
}
void LoadBitmap(char const __flash *bitmap)
{
  
uint16_t i, j,by;
for(i=0; i<64; i+=8)

        for(j=0; j<128; j++)
        {
                   by = FuncFlash((char __flash*)(bitmap++));
                   //by = printf_P(bitmap++);
                   ks0108GotoXY(j, i);
                   ks0108WriteData(by);
                            }

}

Всё работает , даже by = printf_P(bitmap++); не выдаёт ошибку. Правда после 167 ошибки вылезла 27
27 Entry entry in module module (file) redefined in module module (file)
There are two or more entries with the same name. XLINK aborts immediately.
пришлось #include "Bitmap.h" в котором находится массив обявить его как extern ну и прототип функции
соответственно:
Код
Основной модуль программы
//#include "Bitmap.h"

extern void LoadBitmap(char const __flash *bitmap);
extern const __flash char IMAGE[];
int main(void) {
........
........
LoadBitmap(IMAGE);
    while(1);
}

Ну ошибок и нету. Правда проверить на реальном ГЖКИ не могу, нету внутреннего
источника отрицательного напряжения для установки контрассности ну и демоплаты.
Протеус не признаю (люблю "живое" железо) smile.gif

Но непонятки (скрытая тревога) остались. Написал так:
Код
FuncFlash(char const __flash *str_)
{
  while (*str_++ != 0);
}

void LoadBitmap(char const __flash *bitmap)
{
  
uint16_t i, j,by;
for(i=0; i<64; i+=8)

        for(j=0; j<128; j++)
        {
                        by = FuncFlash((char const __flash*)(bitmap++));
                        //by = printf_P(bitmap++);
                        ks0108GotoXY(j, i);
                        ks0108WriteData(by);
                }

}

Появилось предупреждение:
Warning[w6]: Type conflict for external/entry "FuncFlash", in module ks0108 against external/entry in module Bitmap;
function types differ in parameter 1; types have different type attributes
/* In module ks0108: */
/* Function, args 1, attr 0 */
int (__version_3 FuncFlash)(char __flash *);
/* In module Bitmap: */
/* Function, args 1, attr 0 */
int (__version_3 FuncFlash)(char __flash const *);
Прикрепленные файлы
Прикрепленный файл  ks0108.zip ( 61.99 килобайт ) Кол-во скачиваний: 25
 


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 9 2008, 19:55
Сообщение #20


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(sKWO @ Mar 9 2008, 19:44) *
в хедере Bitmap.h массив карты const __flash char IMAGE[];
Неправильно. Вы определили массив в Bitmap.h, теперь, если вы включите этот файл в два (три, несколько) файла, в которым вам потребуется этот массив, в каждом из этих файлов окажется по копии этого массива, а это явно не то, что вы хотели (даже если не считать того, что все эти копии будут иметь одинаковое имя и линкер не будет знать, какой именно из этих массивов использовать). Вам надо было лишь описать этот массив, чтобы компилятор во всех файлах, использующих этот массив имел возможность сгенерировать правильные команды доступа и проверить правильность использования массива программистом. Итак, поскольку массив у вас констатный, лежит во флеш, состоит из uint8_t, то его так и надо описать: uint8_t const __flash IMAGE[128*8]; Причем собственно "тело" этого массива будет описано в другом файле (наверное в Bitmap.c), поэтому в заголовочном файле его надо описать с квалификатором extern:
Код
#ifndef    BITMAP_H    // "стражи" одного включения должны охватывать весь файл
#define BITMAP_H
//  #include <pgmspace.h>  // ИАР понимает __flash беэ включения этого файла, и никакие функции из pgmspace.h в bitmap.h не используются, поэтому и включать его тут не нужно
#include <stdint.h>    // для использования uint8_t и подобных надо включать stdint.h, а не inttypes.h, и полный путь тоже не нужен - выберите Normal DLIB в Project->Options->General->Library Configuration.

extern uint8_t const __flash IMAGE[128*8];
#endif // BITMAP_H
Соответственно определение массива уходит в Bitmap.c: uint8_t const __flash IMAGE[128*8] = { ....... };
Цитата(sKWO @ Mar 9 2008, 19:44) *
в Bitmap.с написал так
Код
FuncFlash(char __flash *str_)
{
  while (*str_++ != 0);
}
Вы не указали тип возвращаемого функцией значения. Если функция ничего не возвращает, то этот тип должен быть void. Странно, что компилятор молча скушал это и подставил int как возвращаемое значение. Это вылезет боком позже. Ваша функция не изменяет данные, к которым обращается через указатель, поэтому возьмите за правило в таких случаях объявлять указатель в параметрах как указатель на константные данные (не важно, что вы там же указываете __flash). Такой подход имеет два плюса - во-первых не помешает вам передавать в такую функцию указатель на неконстантные данные, а во-вторых компилятор обругает вас и спасет от ошибки, если вы внутри функции все же попытаетесь данные изменить. И вам не придется менять это правило при переходе на любой другой процессор или компилятор, у которого нет ключевого слова __flash. Итого: void FuncFlash(char const __flash *str_).
Цитата(sKWO @ Mar 9 2008, 19:44) *
Код
    by = FuncFlash((char __flash*)(bitmap++));
Вот видите - вы поскупились на const в объявлении функции и вам пришлось делать явное приведение типов. Явное приведение - это первый звоночек о не совсем удачной реализации. А уж "убирание" const через явное приведение типа - вообще удар колокола, такое в программе допустимо только в загрузчике, где действительно надо писать в read-only область.
Цитата(sKWO @ Mar 9 2008, 19:44) *
Правда после 167 ошибки вылезла 27
27 Entry entry in module module (file) redefined in module module (file)
There are two or more entries with the same name. XLINK aborts immediately.
пришлось #include "Bitmap.h" в котором находится массив обявить его как extern ну и прототип функции
соответственно:
Вот-вот. Причем не "пришлось", а так и надо было делать сразу.
Цитата(sKWO @ Mar 9 2008, 19:44) *
Появилось предупреждение:
Warning[w6]: Type conflict for external/entry "FuncFlash", in module ks0108 against external/entry in module Bitmap;
У вас эта функция объявлена в двух местах и объявления эти отличаются. Непонятно, что тут вас смущает - просто сделайте все объявления одинаковыми. Именно поэтому объявления функций, используемых более чем в одном файле выносятся в заголовочные файлы - включая заголовочный файл вы всегда подключаете идентичные объявления.

Покопал ks0108.c - оказывается FuncFlash должна что-то возвращать, причем судя по сравнению с '\0' и '\n' - возвращать должна скорее всего char. А у вас она по умолчанию возвращает int - и вы имеете совершенно лишние операции с двухбайтным данным вместо однобайтного.

Попробовал компилировать исходники - там у вас какая-то путаница из char, const char, uint8_t - приведите их в порядок. char используйте только тогда, когда речь идет о символах. Если этот символ не изменяется функцией - используйте char const. Если речь идет о байте - используйте uint8_t, если этот байт в функции не изменяется - uint8_t const. Поверьте, выработав в себе такую дисциплину, вы сократите время понимания своих же исходников и избежите дурацких ошибок. В качестве проверки можете использовать такую - мне удалось выкинуть все явные приведения типов из вашего исходника.

Еще замечание - в ks0108.c у вас есть строчка #include "iom168.h" - она не совсем корректна. Во-первых, в кавычках указывается имя файла, лежащего в текущей директории. А iom168.h находится в директориях компилятора, поэтому его имя надо указывать в угловых скобках. Во-вторых - точно также как в avr-gcc есть файл <avr/io.h> который сам подключает заголовочный файл для нужного процессора, также и у IAR есть заголовочный файл <ioavr.h>, и включать в проект надо его. Тогда сменив в опциях проекта тип процессора вам не придется лазить по всем исходникам и менять везде заголовочный файл.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

2 страниц V  < 1 2
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 27th August 2025 - 16:06
Рейтинг@Mail.ru


Страница сгенерированна за 0.02533 секунд с 7
ELECTRONIX ©2004-2016