|
Прошу совета по индексам массивов |
|
|
|
Nov 8 2006, 12:01
|
Частый гость
 
Группа: Свой
Сообщений: 94
Регистрация: 14-04-05
Из: Россия
Пользователь №: 4 130

|
Цитата(king2 @ Nov 6 2006, 06:02)  начинается какая-то свистопляска, оно выводит содержимое буфера еще раз... Есть какие-нить идеи на эту тему?  какая свистопляска? куда выводит? судя по коду на асме происходит циклическое заполнение массива по адресу usb_buffer+usb_txtail.
Сообщение отредактировал ARIM - Nov 8 2006, 12:05
|
|
|
|
|
Nov 9 2006, 23:58
|
Частый гость
 
Группа: Свой
Сообщений: 91
Регистрация: 26-01-06
Пользователь №: 13 668

|
Цитата(rezident @ Nov 6 2006, 15:57)  Цитата(prottoss @ Nov 6 2006, 17:00)  НИКОГДА, если переменная объявлена как CHAR, компилятор не переделает ее в INT, LONG, LONLONG или FLOAT, если вы прямо ему об этом не укажите...
"Никогда не говори ''никогда''"  Именно так. Цитата(rezident @ Nov 6 2006, 15:57)  Еще раз предлагаю инкремент индекса вынести как отдельную операцию. У меня нет IAR for AVR, чтобы проверить получившийся результат на ассемблере. У меня IAR есть, и по эти граблям я уже ходил в точно такой же ситуации - записи в кольцевой буфер. Индекс массива у IAR - int, даже если он объявлен как char[256]. В данном случае нужно писать так (если usb_txtail объявлен как char): usb_txtail++; usb_buffer[usb_txtail]=0x05; или так: usb_buffer[(usb_txtail++) & 0xff]=0x05;
|
|
|
|
|
Nov 10 2006, 12:19
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(sz36 @ Nov 10 2006, 06:58)  Цитата(rezident @ Nov 6 2006, 15:57)  Цитата(prottoss @ Nov 6 2006, 17:00)  НИКОГДА, если переменная объявлена как CHAR, компилятор не переделает ее в INT, LONG, LONLONG или FLOAT, если вы прямо ему об этом не укажите...
"Никогда не говори ''никогда''" Именно так. Цитата(rezident @ Nov 6 2006, 15:57)  Еще раз предлагаю инкремент индекса вынести как отдельную операцию. У меня нет IAR for AVR, чтобы проверить получившийся результат на ассемблере. У меня IAR есть, и по эти граблям я уже ходил в точно такой же ситуации - записи в кольцевой буфер. Индекс массива у IAR - int, даже если он объявлен как char[256]. В данном случае нужно писать так (если usb_txtail объявлен как char): usb_txtail++; usb_buffer[usb_txtail]=0x05; или так: usb_buffer[(usb_txtail++) & 0xff]=0x05; Бред какой то...Вы первый пост читали? Если нет, то я Вам настоятельно рекомендую...
--------------------
|
|
|
|
|
Nov 13 2006, 14:26
|
Местный
  
Группа: Свой
Сообщений: 255
Регистрация: 17-08-06
Из: Москва
Пользователь №: 19 646

|
Отвечаю сразу всем. Если вынести инкремент в отдельную операцию, получается вот что: Код 84 usb_txtail++; \ 00000026 .... LDI R30, LOW(usb_txtail) \ 00000028 .... LDI R31, (usb_txtail) >> 8 \ 0000002A 8100 LD R16, Z \ 0000002C 9503 INC R16 \ 0000002E 8300 ST Z, R16 85 usb_buffer[usb_txtail]=0x05; \ 00000030 E005 LDI R16, 5 \ 00000032 9120.... LDS R18, usb_txtail \ 00000036 E030 LDI R19, 0 \ 00000038 01F9 MOVW R31:R30, R19:R18 \ 0000003A .... SUBI R30, LOW((-(usb_buffer) & 0xFFFF)) \ 0000003C .... SBCI R31, (-(usb_buffer) & 0xFFFF) >> 8 \ 0000003E 8300 ST Z, R16 От (unsigned char) перед инкрементом или от & 0xFF ничего не меняется. "ОНО" не должно выводить буфер еще раз, потому что вывод написан вот так: Код while (usb_txhead != usb_txtail) { Usb_write_byte(usb_buffer[usb_txhead++]); } По идее, переход от 255 к нулю не должен ничем отличаться от перехода с 10 на 11, например. А фиг.. Даже если заполнять буфер просто инкрементом, то оно потихонечку досчитывает до 255, потом быстро выводит буфер еще раз (уже заполненный) и продолжает. Объявления переменных: Код volatile unsigned char usb_buffer[256]; volatile unsigned char usb_txhead; volatile unsigned char usb_txtail;
|
|
|
|
|
Nov 13 2006, 15:38
|
Местный
  
Группа: Свой
Сообщений: 255
Регистрация: 17-08-06
Из: Москва
Пользователь №: 19 646

|
Цитата(aaarrr @ Nov 13 2006, 17:57)  Цитата(king2 @ Nov 13 2006, 17:26)  "ОНО" не должно выводить буфер еще раз, потому что вывод написан вот так... ...Даже если заполнять буфер просто инкрементом, то оно потихонечку досчитывает до 255, потом быстро выводит буфер еще раз (уже заполненный) и продолжает.
То есть выходит, что проблема имеет место при выводе данных, а не при вводе? Получается, что так. Фишка в том, что блоки и ввода и вывода одинаковые, индекс вывода "догоняет" индекс ввода, пока они не станут равны. И тот и другой только увеличивается, так что по идее, если индекс ввода поменялся 255->0, то и индекс вывода должен поменяться так же (и вывести байтик). А оно так не происходит, вместо этого оно каким-то образом проскакивает через проверку равенства индексов и выводит по-новой весь буфер..
|
|
|
|
|
Nov 13 2006, 16:01
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(king2 @ Nov 13 2006, 22:38)  А оно так не происходит, вместо этого оно каким-то образом проскакивает через проверку равенства индексов и выводит по-новой весь буфер..  Люди! так и не возьму в толк что ВАМ не понятного? ЕСЛИ и индекс обьявлен, как 8-разрядная переменная, то, естественно, какой бы ни был длины массив, хоть 160 гбайт,выше границы 256 элементов массива, ВЫ не выйдите ни когда) Компилятор будет тупо увеличивать разрядность индекса, дополнением его до нужной разрядности дополнением нулей ПРИ ВЫЧИСЛЕНИИ АБСОЛЮТНОГО АДРЕСА ЭЛЕМЕНТА МАССИВА, НО при выходе индекса (при его инкременте-декременте) за пределы объявленной разрядности, индекс будет урезан до той разрядности, которую ВЫ указали компилятору. В крайнем случае, если компилятор посчитает, что есть НЕОДНОЗНАЧНОСТЬ, он (компилятор) предупредит ВАС соответсвующим предупреждением. Ну.
--------------------
|
|
|
|
|
Nov 13 2006, 21:25
|
Местный
  
Группа: Свой
Сообщений: 255
Регистрация: 17-08-06
Из: Москва
Пользователь №: 19 646

|
Посылательный код: Код //! writes byte in FIFO for current endpoint #define Usb_write_byte(byte) (UEDATX = (U8)byte) //! tests if endpoint write allowed #define Is_usb_write_enabled() (UEINTX&(1<<RWAL))
412 while (Is_usb_write_enabled() && (usb_txhead != usb_txtail)) { ^ Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement \ ??loop1: \ 0000028E 910000E8 LDS R16, 232 \ 00000292 2F10 MOV R17, R16 \ 00000294 FF15 SBRS R17, 5 \ 00000296 C014 RJMP ??exit \ 00000298 9100.... LDS R16, usb_txhead \ 0000029C 9110.... LDS R17, usb_txtail \ 000002A0 1701 CP R16, R17 \ 000002A2 F071 BREQ ??exit 413 Usb_write_byte(usb_buffer[usb_txhead++]); \ 000002A4 9100.... LDS R16, usb_txhead \ 000002A8 2F10 MOV R17, R16 \ 000002AA 9513 INC R17 \ 000002AC 9310.... STS usb_txhead, R17 \ 000002B0 E010 LDI R17, 0 \ 000002B2 01F8 MOVW R31:R30, R17:R16 \ 000002B4 .... SUBI R30, LOW((-(usb_buffer) & 0xFFFF)) \ 000002B6 .... SBCI R31, (-(usb_buffer) & 0xFFFF) >> 8 \ 000002B8 8100 LD R16, Z \ 000002BA 930000F1 STS 241, R16 \ 000002BE CFE7 RJMP ??loop1 415 } Вопрос нифига не в том, почему индекс становится 16-битным - тут-то понятно почему, потому что он становится индексом не массива, а памяти, а это как раз unsigned int  Вопрос в том, почему при переходе через 0 оно посылает еще один раз весь буфер. Отличать 0 от 256 символов в буфере не надо, предполагается, что такой ситуации не возникает, а если возникает, то и фиг с ней. В данном примере ее реально не возникает, всегда реальных данных меньше чем 64 байт.
|
|
|
|
|
Nov 14 2006, 06:48
|
Местный
  
Группа: Свой
Сообщений: 278
Регистрация: 18-01-05
Из: Санкт-Петербург
Пользователь №: 2 031

|
Цитата Вопрос в том, почему при переходе через 0 оно посылает еще один раз весь буфер. потому что при переходе через ноль (usb_txhead != usb_txtail) условие Код (usb_txhead != usb_txtail) вы приводили почти во всех примерах, а как меняется usb_txtail вы не показывали.
|
|
|
|
|
Nov 14 2006, 13:45
|
Местный
  
Группа: Свой
Сообщений: 255
Регистрация: 17-08-06
Из: Москва
Пользователь №: 19 646

|
Цитата(_Sam_ @ Nov 14 2006, 09:48)  Цитата Вопрос в том, почему при переходе через 0 оно посылает еще один раз весь буфер. потому что при переходе через ноль (usb_txhead != usb_txtail) условие Код (usb_txhead != usb_txtail) вы приводили почти во всех примерах, а как меняется usb_txtail вы не показывали. Здесь я написал как оно из буфера выводится (инкремент usb_txtail), в первом посте написал как в буфер запихивается (инкремент usb_txhead). Не понимаю, почему условие НЕРАВЕНСТВА должно по другому работать, если одна из сравниваемых переменных равна нулю.
|
|
|
|
|
Nov 15 2006, 06:43
|
Местный
  
Группа: Свой
Сообщений: 278
Регистрация: 18-01-05
Из: Санкт-Петербург
Пользователь №: 2 031

|
Могли бы и целиком код привести. И указать в этом целом куске что конкретно не работает. Вот попытался как-то обобщить то что вы писали. Код #include "stdio.h"
volatile unsigned char usb_buffer[256]; volatile unsigned char usb_txhead = 1; // начинаем вывод с первого элемента volatile unsigned char usb_txtail = 255; // чтобы при выполнении цикла usb_txtail == 0
int main( void ){ usb_buffer[usb_txtail++]=0x05; while (usb_txhead != usb_txtail) { // Is_usb_write_enabled() я убрал, т.к. не знаю что такое UEDATX и UEINTX printf("%i - %i\n",usb_buffer[usb_txhead++],usb_txhead); // функцию Usb_write_byte заменил на printf } return 0; } У меня всё работает и буфер выводится один раз несмотря на переполнение индекса! Компилятор и отладчик использовал IAR. Формат printf - medium.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|