|
Ламерские вопросы по Си, перехожу с асма |
|
|
|
May 19 2012, 06:34
|
Профессионал
    
Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256

|
Добрый день. Копаю интернет, но все как-то безуспешно. Хочу написать функцию передачи строки по UART, работающую по прерыванию. Причем строка может быть как константа (храниться во флэш), так и переменная (храниться в СОЗУ). Код #define size_TX0 10 volatile static int8_t count_TX0;//кол-во непереданных символов в буфере UART0 volatile static int8_t index_TX0;//адресация в буфере передачи UART0 volatile static int8_t bufferTX0[size_TX0];//массив - буфер передачи UART0 /*==============================*/ void send_UART0(char *string) { int8_t i; for(i=0;*string!='\0';i++) { bufferTX0[i]=(*string); //сохраняем строку в буфер string++; count_TX0++; //считаем символы } index_TX0=0; //обнуляем адресацию в буфере sbi(UCSR0B,UDRIE0); //запускаем прерывание } /*==============================*/ ISR(USART0_UDRE_vect) { UDR0 = bufferTX0[index_TX0++]; // Берем данные из буффера. if(index_TX0==count_TX0) cbi(UCSR0B,UDRIE0); // Если все передали, то выкл.прерывание } /*==============================*/ Пишу send_UART0("12345");, но эти 12345 сохраняются в СОЗУ. Вопрос: как передать в функцию строку, чтобы она сохранилась во флэш? Спасибо.
Сообщение отредактировал Alt.F4 - May 19 2012, 06:36
|
|
|
|
|
May 19 2012, 07:54
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Хм... Я не силён в терминологии разряда «цветовой дифференциации штанов», но в моём понимании «ламер» означает человека, который не просто не знает чего-то (все чего-то не знают *) ), а и не желает разобраться и при этом ещё пробует учить других. «ламерский вопрос» при этом редкость и обычно сам он своим уровнем хорошо показывает, что в предыдущих своих сообщениях человек с умным видом рассуждал о том, чего совершенно не знает. «нуб», в отличие от «ламера», хочет что-от узнать. Один и тот же вопрос может быть «ламерским» или «чайниковским» в зависимости от того, кто его задал (от предистории). Ну да не важно. Судя по тому, что соседний вопрос был по AVR Studio, используется avr-gcc. У него до версии 4.7 не поддерживаются разные пространства памяти и соответствующие модификаторы указателей (да и в 4.7, если я правильно понял, это есть в C frontend, но нет в C++). Так что нужно использовать атрибут размещения из avr/pgmspace.hУниверсальную функцию написать можно, сначала придумав, как передавать признак ОЗУ/флеш. Две специальных написать проще и результат не хуже. И это будет выглядеть как-то так: CODE #include <avr/pgmspace.h>
#define size_TX0 10
// беззнаковые счётчики и индексы дают код короче и быстрее volatile static unt8_t count_TX0; //кол-во непереданных символов в буфере UART0 volatile static unt8_t index_TX0; //адресация в буфере передачи UART0 // char так char, какая нам разница, какой размер и знак у символов volatile static char bufferTX0[size_TX0];//массив - буфер передачи UART0 ...
void wait_UART0() { while (UCSR0B & (1<<UDRIE0)) {} }
void start_UART0() { index_TX0 = 0; UCSR0B |= (1<<UDRIE0); }
// Строка из ОЗУ void send_UART0(char *string) { char *dst = buffer_TX0; char ch;
wait_UART0(); // надо ведь дождаться, пока уйдёт предыдущая строка
count_TX0 = 0;
// бесконечный цикл, тут прямо в условие действия затолкать для новичка возможно слишком уж нечитаемо выйдет for (;;) { ch = *string++; // если достигнут конец строки или уже нет местя в буфере — выходим if (ch == '\0' || ++count_TX0 >= size_TX0) break; *dst++ = ch; }
start_UART0(); }
... // Строка из флеша. // Увы, нормальной поддержки указатеелй во флеше нет, поэтому проще не обманывать себя void send_UART0_P(unsigned string_address) { char *dst = buffer_TX0; char ch;
wait_UART0();
count_TX0 = 0;
for (;;) { ch = pgm_read_byte(string_address); ++string_address; if ( ch == '\0' || ++count_TX0 >= size_TX0) break; *dst++ = ch; }
start_UART0(); }
... send_UART0_P( PSTR("Temperature: ") ); // эта строка не попадёт в ОЗУ char tmpbuf[size_TX0]; // к примеру, преобразовали в буфер число send_UART0( tmpbuf ); send_UART0_P( PSTR("\r\n") ); // эта строка не попадёт в ОЗУ
____________ *) Не знать — не стыдно. Стыдно не хотеть узнать.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
May 19 2012, 20:32
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(Dog Pawlowa @ May 19 2012, 10:19)  Но с универсальной функцией придется еще пободаться. да, можно её и так боднуть:-) http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gc...r-Builtins.htmlЦитата(ReAl @ May 19 2012, 10:54)  Универсальную функцию написать можно, сначала придумав, как передавать признак ОЗУ/флеш. А зачем передавать, можно на ходу макрос разворачивать и определять PGM_P она или нет.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
May 20 2012, 11:17
|
Профессионал
    
Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256

|
Цитата Две специальных написать проще и результат не хуже. И это будет выглядеть как-то так: ... Спасибо большое!!! У себя реализовал так: Код void start_UART0_TX() { index_TX0 = 0; //обнуляем адресацию в буфере передачи sbi(UCSR0B,UDRIE0); //запускаем прерывание } /*--------------------------*/ void send_UART0(char *string) { u08 i; count_TX0 = 0; for(i=0;*string!='\0' && count_TX0<size_TX0;i++) { bufferTX0[i]=(*string++); //сохраняем строку в буфер count_TX0++; //считаем символы } start_UART0_TX(); //запускаем прерывание }
void send_UART0_P(const char *string) { u08 i; count_TX0 = 0; for(i=0;pgm_read_byte(string)!='\0' && count_TX0<size_TX0;i++) { bufferTX0[i]=pgm_read_byte(string++); //сохраняем строку в буфер count_TX0++; //считаем символы } start_UART0_TX(); //запускаем прерывание } /*--------------------------*/ ISR(USART0_UDRE_vect) { UDR0 = bufferTX0[index_TX0++]; // Берем данные из буффера. if(index_TX0>=count_TX0) cbi(UCSR0B,UDRIE0); // Если все передали, то выкл.прерывание }
Сообщение отредактировал Alt.F4 - May 20 2012, 11:21
|
|
|
|
|
May 21 2012, 00:33
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Строки наверное удобней выводить printf'ом. format str размещать во флеш, а %s - для вывода строк формируемых в run-time в ОЗУ... WinAVR поддерживает макросы с переменным числом аргументов Код #define pgm_printf(x, ...) do {\ static const char PROGMEM pgm_str[] = x;\ char pgm_data_buf[sizeof(pgm_str)];\ __pgm_strcpy( pgm_data_buf, pgm_str);\ printf( pgm_data_buf, __VA_ARGS__);\ } while(0)
void __pgm_strcpy(char *dst, const char PROGMEM *str) { do { *dst++ = *str; } while (*str++); }
примеры использования:
pgm_printf("strlen(%s) = %u\n", "hello", strlen("hello")); pgm_printf("x = %d\n", 123); pgm_printf("addr_0x%x\n", 0x1000);
|
|
|
|
|
May 23 2012, 03:11
|
Профессионал
    
Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256

|
Возник новый вопрос. Прочел, что хорошим тоном является при написании макросов, в том числе многострочных, заключать их в do{...}while(0) Но вот беда, когда я заключаю в этот цикл while следующий макрос, он компилируется хрен знает каким образом. Исходный вариант: Код #define check_temp(X)\ if(temp==X) {index_RX0++;break;}\ goto start_RX0; В цикле while: Код #define check_temp(X)\ do{\ if(temp==X) {index_RX0++;break;}\ goto start_RX0;\ }while(0) Макрос вставляю в case инструкции switch. В дизасемблере второй макрос выполняет два раза index_RX0+, затем джамп и перед ret обнуляет index_RX0!!! Если do{...}while(0) убрать, то все работает как надо. Что это может быть? Спасибо.
Сообщение отредактировал Alt.F4 - May 23 2012, 03:12
|
|
|
|
|
May 23 2012, 05:48
|

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

|
QUOTE (Alt.F4 @ May 23 2012, 06:11)  Что это может быть? Во втором случае break выходит из do{}while(), а не из case(). P.S. на будущее - заключайте X внутри макроса в скобки. В месте вызова он может оказаться не переменной, а выражением.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jun 2 2012, 15:11
|
Профессионал
    
Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256

|
Имеем массив в EEPROM и указатель на него: Код EEMEM char array[10]; unsigned int *addr_EE; addr_EE = array; <-- здесь компилятор ругается на несовпадение типов. EEAR = addr_EE; Подскажите пожалуйста, как правильно объявить указатель? Спасибо.
Сообщение отредактировал Alt.F4 - Jun 2 2012, 15:14
|
|
|
|
|
Jun 2 2012, 15:27
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(Alt.F4 @ Jun 2 2012, 18:11)  Имеем массив в EEPROM и указатель на него: Код EEMEM char array[10]; unsigned int *addr_EE; addr_EE = array; <-- здесь компилятор ругается на несовпадение типов. EEAR = addr_EE; Подскажите пожалуйста, как правильно объявить указатель? Спасибо. Думаю что так: Код EEMEM char array[10]; EEMEM char *addr_EE; или так можно: Код unsigned int addr_EE; addr_EE = (unsigned int)array; EEAR = addr_EE;
|
|
|
|
|
Jun 2 2012, 15:32
|

Профессионал
    
Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409

|
Цитата(Alt.F4 @ Jun 2 2012, 18:11)  Имеем массив в EEPROM и указатель на него: Код EEMEM char array[10]; unsigned int *addr_EE; addr_EE = array; <-- здесь компилятор ругается на несовпадение типов. EEAR = addr_EE; Подскажите пожалуйста, как правильно объявить указатель? Спасибо. У Вас array объявлен как EEMEM char а указатель на тип данных int. Указатель должен соответсвовать типу данных или приводится к нему. в IAR прокатила бы такая такая запись Код __eeprom char array[10]; char __eeprom *addr_EE; addr_EE = array;
|
|
|
|
|
Jun 2 2012, 15:42
|
Профессионал
    
Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256

|
Цитата или так можно: Код unsigned int addr_EE; addr_EE = (unsigned int)array; EEAR = addr_EE; Разницы от исходника компилятор не заметил, т.е. типы не совпадают. Цитата Думаю что так: Код EEMEM char array[10]; EEMEM char *addr_EE; Если делать так, то варнинг несовпадения типов выскакивает уже напротив: EEAR = addr_EE;Цитата Указатель должен соответсвовать типу данных или приводится к нему. Каким образом привести тип указателя, чтобы его значение можно было записать в EEAR и в тоже время в этот указатель можно записать адрес массива?
Сообщение отредактировал Alt.F4 - Jun 2 2012, 15:48
|
|
|
|
|
Aug 6 2012, 12:33
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(Alt.F4 @ Aug 6 2012, 13:14)  ё-мана, это оказывается в Source Files (AVR Studio 4) надо добавлять все файлы с расширением *.c, я думал компилятор все сам подключит. Ы, откуда он (компилятор) узнает, что именно ему надо компилировать? Как раз-таки из содержимого файла проекта. Чистологика и никакого обману  Есть люди, которые любят написать makefile типа раз и навсегда, в т.ч. предусмотреть, чтобы компилилось всё, что находится в папке проекта *.S, *.c, *.cpp Лично мне такое не нравится, но их тоже понять можно: а нефиг посторонним исходникам делать в проекте! Так что выбирайте себе концепцию по душе.
Сообщение отредактировал _Pasha - Aug 6 2012, 12:35
|
|
|
|
|
Aug 6 2012, 18:45
|
Местный
  
Группа: Участник
Сообщений: 313
Регистрация: 2-07-11
Пользователь №: 66 023

|
Цитата(_Pasha @ Aug 6 2012, 16:33)  но их тоже понять можно: а нефиг посторонним исходникам делать в проекте! Чтобы ограничить потери случайно испортив файл, часто делаю его копии в ту же папку. В проводнике "Копировать" и сразу "Вставить". В папке есть "www.c", "Копия www.c", "Копия (2) www.c" и т.д.
|
|
|
|
|
Aug 7 2012, 03:43
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(Сергей Борщ @ Aug 7 2012, 01:00)  В Far-подобном файловом менеджере Shift-F6, End, _ Если копировать, то Shift+ F5. Хотя зачем копировать, когда есть svn - не очень понятно. А я для временного исключения файла из проекта делаю папку unused и перемещаю файл туда (эклипсе говорю, чтоб не трогала эту папку).
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Oct 4 2012, 07:03
|
Профессионал
    
Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256

|
Подскажите, пожалуйста, как описать массив структур FontTable, все время ругается на несовместимость типа указателя? Спасибо. Код typedef struct { uint8_t code; // код символа ASCII uint8_t * index; // указатель на массив символа uint8_t width; // ширина символа } FontStruct;
const FontStruct FontTable[] = { {0x31, &font_0x31,6}, {0x32, &font_0x32,6}, {0x33, &font_0x33,6}}
/*---------------------------------------------------------------------------------*/ static const uint8_t font_0x31[6] PROGMEM = {0x00,0x81,0xff,0x80,0x00,0x00}; static const uint8_t font_0x32[6] PROGMEM = {0x82,0xc1,0xa1,0x91,0x8e,0x00}; static const uint8_t font_0x33[6] PROGMEM = {0x42,0x81,0x89,0x89,0x76,0x00};
Сообщение отредактировал Alt.F4 - Oct 4 2012, 07:51
|
|
|
|
|
Oct 4 2012, 07:23
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(Alt.F4 @ Oct 4 2012, 11:03)  Подскажите, пожалуйста, как описать массив структур FontTable, все время ругается на несовместимость типа указателя? Спасибо. Вот так: Код const FontStruct FontTable[] = { {0x31, font_0x31,6}, {0x32, font_0x32,6}, {0x33, font_0x33,6}} Имя массива - уже указатель.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Oct 4 2012, 08:20
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(Alt.F4 @ Oct 4 2012, 10:03)  Подскажите, пожалуйста, как описать массив структур FontTable, все время ругается на несовместимость типа указателя? Спасибо. Потому что Код uint8_t * - указатель на байт в ОЗУ, а font_0x31 Код PROGMEM то есть во flash находится.
|
|
|
|
|
Oct 4 2012, 08:28
|
Профессионал
    
Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256

|
А как тогда объявить указатель на массив во флэш? з.ы. Ради интереса удалил PROGMEM, ничего не поменялось. Пишет: ../font.h:1660:3: warning: initialization discards qualifiers from pointer target type Добавлено:Удалил "static const" перед uint8_t font_0x31[6] PROGMEM и варнинг пропал, но по прежнему выдает какую-то ошибку и она почему-то не отображается в билдере... Добавлено еще раз:Фув, наконец-то скомпилировалось. Вчера полдня и сегодня до обеда сходил с ума
Сообщение отредактировал Alt.F4 - Oct 4 2012, 08:43
|
|
|
|
|
Oct 4 2012, 08:37
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(Alt.F4 @ Oct 4 2012, 11:51)  MrYuran, компилятор пишет: ../font.h:1362:3: warning: initialization from incompatible pointer type Так это ж не ругается, так, под нос бухтит  Может, так попробовать: static const* uint8_t font_0x31 PROGMEM = {0x00,0x81,0xff,0x80,0x00,0x00};
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Oct 4 2012, 08:41
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(Alt.F4 @ Oct 4 2012, 11:28)  з.ы. Ради интереса удалил PROGMEM, ничего не поменялось. Пишет: ../font.h:1660:3: warning: initialization discards qualifiers from pointer target type Напишите так Код uint8_t font_0x31[6] = {0x00,0x81,0xff,0x80,0x00,0x00}; uint8_t font_0x32[6] = {0x82,0xc1,0xa1,0x91,0x8e,0x00}; uint8_t font_0x33[6] = {0x42,0x81,0x89,0x89,0x76,0x00};
const FontStruct FontTable[] = { {0x31, font_0x31,6}, {0x32, font_0x32,6}, {0x33, font_0x33,6}}; - без static const и без &.
|
|
|
|
|
Oct 4 2012, 12:02
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Код typedef struct { uint8_t code; const uint8_t* index; // указатель на КОНСТАНТНЫЙ массив (не хватало квалификатора const) uint8_t width; } FontStruct;
const FontStruct FontTable[] = { {0x31, &font_0x31[0], 6}, // И тут тоже косяк был. Надо либо брать адрес нулевого элемента массива, либо просто имя массива без взятия адреса. {0x32, &font_0x32[0], 6}, {0x33, &font_0x33[0], 6} }; А в остальном у вас всё изначально правильно и static const к месту и PROGMEM. Правда FontTable тоже во флешь можно разместить...
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Oct 5 2012, 05:47
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(_Артём_ @ Oct 4 2012, 23:39)  Не совсем так. В avr-gcc const uint8_t* ptr при простом разыменовывании указателя всегда обращается к ОЗУ, а чтобы читать из флеша или eeprom нужно через макросы мыкаться: pgm_read_byte(ptr) и eeprom_read_byte(ptr). Что как раз не так удобно как в IAR. Но и в avr-gcc 4.7.0 тоже появилась аналогичная IARу фича: ключевое слово __flash и теперь стало возможно Код const __flash uint8_t x1 = 33; const __flash uint8_t x2 = 36; const __flash uint8_t* ptr = &x1; if (*ptr==x2) { ... } Цитата(Alt.F4 @ Oct 4 2012, 22:29)  пока надоело бодаться с этим компилятором, придирается ко всяким мелочам. Это никакие не мелочи. Просто нужно один раз разобраться в теме и получать удовольствие от работы... Для тренировки ответьте себе на следующий вопрос, чем отличаются следующие указатели: Код char* p1; const char* p2; char* const p3; const char* const p4;
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Oct 5 2012, 09:47
|
Профессионал
    
Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256

|
Цитата а чтобы читать из флеша или eeprom нужно через макросы мыкаться: pgm_read_byte(ptr) и eeprom_read_byte(ptr). Миллионным перебором вариантов стал объявлять адрес для ЕЕ как void* adrr;  А для чтения свой макрос написал (не знал, что есть eeprom_read_byte()): Код #define EE_read {\ cli();\ EEAR = (u16)addr++;\ sbi(EECR,EERE);\ temp = EEDR;\ EEAR = 0;\ sei();} Цитата Для тренировки ответьте себе на следующий вопрос, чем отличаются следующие указатели: Вроде бы так: char* p1; - переменный указатель на массив типа char const char* p2; - указатель константа на массив типа char (хотя он все равно будет размещен в ОЗУ как и первый) char* const p3; - тоже самое const char* const p4; - тоже самое
Сообщение отредактировал Alt.F4 - Oct 5 2012, 09:47
|
|
|
|
|
Oct 5 2012, 10:39
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(Alt.F4 @ Oct 5 2012, 13:47)  Вроде бы так: Нет не так. Отсюда и все проблемы.. char* p1; - указатель на char const char* p2; - указатель на const char char* const p3; - константный указатель на char const char* const p4; - константный указатель на const char Пока вы азы языка Си не поймёте, так и будете ходить по граблям, занимаясь подбором-перебором и изобретая очередные грабли. Остановитесь, почитайте азы - сразу увидите как всё станет понятно и красиво. Цитата(Alt.F4 @ Oct 5 2012, 13:47)  А для чтения свой макрос написал (не знал, что есть eeprom_read_byte()) Зря... Достаточно #include <avr/eeprom.h> и в путь. В avrlibc очень оптимально написано, что касается eeprom, да многое другое тоже.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Oct 5 2012, 14:13
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(demiurg_spb @ Oct 5 2012, 08:47)  Не совсем так. В avr-gcc const uint8_t* ptr при простом разыменовывании указателя всегда обращается к ОЗУ, а чтобы читать из флеша или eeprom нужно через макросы мыкаться: pgm_read_byte(ptr) и eeprom_read_byte(ptr). Сделал так: Код const uint8_t PROGMEM test[3]={1, 2, 4}; const uint8_t test2[3]={11,12,16}; const uint8_t * ptr; volatile uint8_t test_copy[9]; __attribute__ ((section (".eeprom"))) const uint8_t test3[3]={'A','B','m'}; int main() { ptr=test; test_copy[0]=ptr[0]; test_copy[1]=ptr[1]; test_copy[2]=ptr[2];
ptr=test2; test_copy[3]=ptr[0]; test_copy[4]=ptr[1]; test_copy[5]=ptr[2];
ptr=test3; test_copy[6]=ptr[0]; test_copy[7]=ptr[1]; test_copy[8]=ptr[2]; Но похоже GCC просто соптимизировал чтение. Если массивы объявить не как const, работать не будет.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|