static const char * const headersOfHttpResponse_200_ok[] PROGMEM = {//массив указателей на строки, расположенные в памяти программ HTTP_1_1_200_OK_rn_pstr, ContentType_text_html_rn_pstr, CRLFCRLF_pstr };
//Массив структур инициализируем сразу! HeadersOfHttpResponse availableHeadersOfHttpResponse[] = {//доступные HTTP-ответы //индекс массива 0 (приведён для примера) {//HTTP-код 200 200, //HTTP-код (StatusCode) 3, //количество строк в массиве headersOfHttpResponse_200_ok //именованный массив указателей на строки, расположенные в памяти программ }, //индекс массива 1. Ничем не отличается от нулевого, кроме способа инициализации указателя на массив указателей {//HTTP-код 200 200, //HTTP-код (StatusCode) 3, //количество строк в массиве (const char * const[]) {//анонимный массив указателей на строки, расположенные в памяти программ HTTP_1_1_200_OK_rn_pstr, ContentType_text_html_rn_pstr, CRLFCRLF_pstr } }, //индекс массива 2 {//HTTP-код 500 500, //HTTP-код (StatusCode) 3, //количество строк в массиве (const char * const[]){//анонимный массив указателей на строки, расположенные в памяти программ HTTP_1_1_500_Internal_Server_Error_rn_pstr, ContentType_text_html_rn_pstr, CRLFCRLF_pstr } }, };
Кратко опишу весь этот "зоопарк". "availableHeadersOfHttpResponse[]" — глобальный массив доступных в программе HTTP-ответов. Когда сервер решает ответить на запрос, например, кодом "200", то он ищет соответствие среди элементов данного массива. И отправляет соответствующие строки заголовков, а потом уже запрошенный файл. Строки распологаются в памяти программ.
Собственно, код компилируется без варнингов. Компилятор (AVR Studio v4.19) молчит как партизан. Чтение строк массива "availableHeadersOfHttpResponse[0].headersOfHttpResponse" происходит корректно. А вот чтение строк из массивов "availableHeadersOfHttpResponse[1].headersOfHttpResponse" и "availableHeadersOfHttpResponse[2].headersOfHttpResponse" выдаёт всё что угодно, но только не то что надо! Я так понимаю указатель ".headersOfHttpResponse" указывает куда-то не туда. Так вот вопрос. Как обойтись только анонимными массивами, без массивов типа "static const char * const headersOfHttpResponse_200_ok[] PROGMEM"? Методом научного тыка, перепробовал массу разных комбинаций.
_________________ Когда уже ничего не помогает - прочтите, наконец, инструкцию. Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII) Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
пора отказываться от геморроя с pgm_read_xxx, применяйте модификатор __flash и работайте полноценно с "переменными" во flash и указателями на данные там же. модификатор __flash (и __memx, кстати - тоже неплохая фишка) доступен с версии avr-gcc 5.x.x (по-моему, сам я на 6-й сижу, но есть уже и .
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
_________________ Когда уже ничего не помогает - прочтите, наконец, инструкцию. Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII) Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Походу это те же яйца, только в профиль. Обертка того же pgm_read'а. В обоих случаях компилятор сотворит закидывание адреса чтения в ZL,ZH и выполнит LPM Rxx, Z[+] Причем меня сильно гложет сомнение, что если читать циклом массив данных, то gcc поймет это и будет использовать директиву с автоинкрементом Z. С __flash не пробовал, но вот такую конструкцию
// prepare the webpage by writing the data to the tcp send buffer uint16_t print_webpage(uint8_t *buf,uint8_t on_off) { uint16_t plen; plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nPragma: no-cache\r\n\r\n")); plen=fill_tcp_data_p(buf,plen,PSTR("<center><p>Output is: ")); if (on_off){ plen=fill_tcp_data_p(buf,plen,PSTR("<font color=\"#00FF00\"> ON</font>")); }else{ plen=fill_tcp_data_p(buf,plen,PSTR("OFF")); } plen=fill_tcp_data_p(buf,plen,PSTR(" <small><a href=\".\">[refresh status]</a></small></p>\n<p><a href=\".")); if (on_off){ plen=fill_tcp_data_p(buf,plen,PSTR("/0\">Switch off</a><p>")); }else{ plen=fill_tcp_data_p(buf,plen,PSTR("/1\">Switch on</a><p>")); } plen=fill_tcp_data_p(buf,plen,PSTR("</center><hr><br>version 2.17, tuxgraphics.org\n")); return(plen); }
Код:
// fill in tcp data at position pos. pos=0 means start of // tcp data. Returns the position at which the string after // this string could be filled. uint16_t fill_tcp_data_p(uint8_t *buf,uint16_t pos, const prog_char *progmem_s) { char c; // fill in tcp data at position pos // // with no options the data starts after the checksum + 2 more bytes (urgent ptr) while ((c = pgm_read_byte(progmem_s++))) { buf[TCP_CHECKSUM_L_P+3+pos]=c; pos++; } return(pos); }
И я не уверен, что __flash скомпилируется по другому. Но pgm_read дает более полное понимание того, что делается.
я вас уверяю, что не смотря на то, что компилятор делает то же самое, для вас более полное понимание того, что делается, будет именно в случае __flash.
простой пример: вы храните в FLASH массив, состоящий из указателей на массивы структур (тоже во FLASH), внутри которых тоже указатели на другие данные во FLASH (такое запросто бывает в случае организации меню многоуровневого, например). просто напишите что-то аналогичное этому:
c использованием pgm_read_xxxx... думаю, у вас будет такой огород преобразования типов, и все равно разыменование указателей из FLASH так просто не получится сделать без промежуточных pgm_read_xxxx...
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
более полное понимание того, что делается, будет именно в случае __flash
Может быть, тут уж кто как привык.
Я железнозависимые вещи вообще стараюсь выносить в HAL либо в другую библиотеку. Там один раз чтение обернуть в макрос или функцию - и забыть.
для основной программы это вообще должно быть некоей функцией getHttpResponseStr(unsigned char responseIndex, char* responseBuf);
А хранить массив строк во флеше AVR'ок можно либо объявив каждую строку как свой массив и потом сложить массив указателей на строки, либо пожертвовать неким объемом флеша и объявить двумерный массив с явным указанием максимальной длины строк...
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 33
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения