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

 
 
2 страниц V  < 1 2  
Reply to this topicStart new topic
> Прошу совета по индексам массивов
prottoss
сообщение Nov 8 2006, 08:30
Сообщение #16


Гуру
******

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



Цитата(_Sam_ @ Nov 8 2006, 15:06) *
Цитата
начинается какая-то свистопляска, оно выводит содержимое буфера еще раз...

А "оно" и должно выводить ещё раз! Индекс то обнулился! biggrin.gif
Цитата
И хотя инкремент индекса, в приципе тоже арифметическая операция

Было сказано про арифметические операции в которых участвуют переменные разных типов wink.gif
Да, я про последнюю строчку автора совсем забыл...))) Ему надо еще (учиться & * 3), как завещал великий Ленин biggrin.gif


--------------------
Go to the top of the page
 
+Quote Post
ARIM
сообщение Nov 8 2006, 12:01
Сообщение #17


Частый гость
**

Группа: Свой
Сообщений: 94
Регистрация: 14-04-05
Из: Россия
Пользователь №: 4 130



Цитата(king2 @ Nov 6 2006, 06:02) *
начинается какая-то свистопляска, оно выводит содержимое буфера еще раз...

Есть какие-нить идеи на эту тему? smile.gif

какая свистопляска? куда выводит?
судя по коду на асме происходит циклическое заполнение массива по адресу usb_buffer+usb_txtail.

Сообщение отредактировал ARIM - Nov 8 2006, 12:05
Go to the top of the page
 
+Quote Post
sz36
сообщение Nov 9 2006, 23:58
Сообщение #18


Частый гость
**

Группа: Свой
Сообщений: 91
Регистрация: 26-01-06
Пользователь №: 13 668



Цитата(rezident @ Nov 6 2006, 15:57) *
Цитата(prottoss @ Nov 6 2006, 17:00) *

НИКОГДА, если переменная объявлена как CHAR, компилятор не переделает ее в INT, LONG, LONLONG или FLOAT, если вы прямо ему об этом не укажите...

"Никогда не говори ''никогда''" smile.gif

Именно так.

Цитата(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;
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 10 2006, 12:19
Сообщение #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, если вы прямо ему об этом не укажите...

"Никогда не говори ''никогда''" smile.gif

Именно так.

Цитата(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;

Бред какой то...Вы первый пост читали? Если нет, то я Вам настоятельно рекомендую...


--------------------
Go to the top of the page
 
+Quote Post
king2
сообщение Nov 13 2006, 14:26
Сообщение #20


Местный
***

Группа: Свой
Сообщений: 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;
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 13 2006, 14:57
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(king2 @ Nov 13 2006, 17:26) *
"ОНО" не должно выводить буфер еще раз, потому что вывод написан вот так...
...Даже если заполнять буфер просто инкрементом, то оно потихонечку досчитывает до 255, потом быстро выводит буфер еще раз (уже заполненный) и продолжает.

То есть выходит, что проблема имеет место при выводе данных, а не при вводе?
Go to the top of the page
 
+Quote Post
king2
сообщение Nov 13 2006, 15:38
Сообщение #22


Местный
***

Группа: Свой
Сообщений: 255
Регистрация: 17-08-06
Из: Москва
Пользователь №: 19 646



Цитата(aaarrr @ Nov 13 2006, 17:57) *
Цитата(king2 @ Nov 13 2006, 17:26) *

"ОНО" не должно выводить буфер еще раз, потому что вывод написан вот так...
...Даже если заполнять буфер просто инкрементом, то оно потихонечку досчитывает до 255, потом быстро выводит буфер еще раз (уже заполненный) и продолжает.

То есть выходит, что проблема имеет место при выводе данных, а не при вводе?

Получается, что так. Фишка в том, что блоки и ввода и вывода одинаковые, индекс вывода "догоняет" индекс ввода, пока они не станут равны. И тот и другой только увеличивается, так что по идее, если индекс ввода поменялся 255->0, то и индекс вывода должен поменяться так же (и вывести байтик).
А оно так не происходит, вместо этого оно каким-то образом проскакивает через проверку равенства индексов и выводит по-новой весь буфер.. sad.gif
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 13 2006, 16:01
Сообщение #23


Гуру
******

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



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


--------------------
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 13 2006, 16:04
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



А как при условии равенства индексов определить, содержит буфер 0 или 256 байт?

Usb_write_byte() - это, случайно, не макрос?

А вообще, rezident правильно написал по поводу контроля за состоянием указателя.
Go to the top of the page
 
+Quote Post
king2
сообщение Nov 13 2006, 21:25
Сообщение #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 smile.gif

Вопрос в том, почему при переходе через 0 оно посылает еще один раз весь буфер.

Отличать 0 от 256 символов в буфере не надо, предполагается, что такой ситуации не возникает, а если возникает, то и фиг с ней. В данном примере ее реально не возникает, всегда реальных данных меньше чем 64 байт.
Go to the top of the page
 
+Quote Post
_Sam_
сообщение Nov 14 2006, 06:48
Сообщение #26


Местный
***

Группа: Свой
Сообщений: 278
Регистрация: 18-01-05
Из: Санкт-Петербург
Пользователь №: 2 031



Цитата
Вопрос в том, почему при переходе через 0 оно посылает еще один раз весь буфер.

потому что при переходе через ноль (usb_txhead != usb_txtail)

условие
Код
(usb_txhead != usb_txtail)
вы приводили почти во всех примерах, а как меняется usb_txtail вы не показывали.
Go to the top of the page
 
+Quote Post
king2
сообщение Nov 14 2006, 13:45
Сообщение #27


Местный
***

Группа: Свой
Сообщений: 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).

Не понимаю, почему условие НЕРАВЕНСТВА должно по другому работать, если одна из сравниваемых переменных равна нулю.
Go to the top of the page
 
+Quote Post
_Sam_
сообщение Nov 15 2006, 06:43
Сообщение #28


Местный
***

Группа: Свой
Сообщений: 278
Регистрация: 18-01-05
Из: Санкт-Петербург
Пользователь №: 2 031



Могли бы и целиком код привести. И указать в этом целом куске что конкретно не работает. excl.gif

Вот попытался как-то обобщить то что вы писали.
Код
#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.
Go to the top of the page
 
+Quote Post
king2
сообщение Nov 22 2006, 00:56
Сообщение #29


Местный
***

Группа: Свой
Сообщений: 255
Регистрация: 17-08-06
Из: Москва
Пользователь №: 19 646



Итак, проблема найдена, вопрос закрыт.

Дело было в программе на windows, в которую лился поток данных, задержка на обработку добавления в визуальный элемент была ТОЧНО на 4 буфера при постоянной передаче, поэтому создавалось впечатление, что не то скипается, не то повторно передается 256 байт. На самом деле виндовая программа не давала принимать данные точно на размер одного "кольца" по буферу. Если буфер сделать на один байт меньше, эффект был не так очевиден и я просто его не заметил.

Спасибо большое всем за помощь!
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 19th July 2025 - 00:01
Рейтинг@Mail.ru


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