|
лог некой шины, Как это реализовать более оптимально? |
|
|
|
Jul 1 2011, 13:07
|
Местный
  
Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940

|
Цитата А в пятой студии свой компилятор? Так же как и в WInAVR, в AStudio использует GNU-toolchain. Про версии не помню, но файлы в каталогах \avr\bin\ совпадают Цитата Или кратно 256 и буфер на границе. 5 команд - но 7 тактов (или 6, если контроль на 1 байт). Однако вполне можно сократить до 5 тактов, причем с контролем на 16-битный адрес Согласен: Код ldi r31,0x04 ldi r30,0x00 ldi r25,0x02 ldi r24,0x00 ;cycle: in r18, 0x19 st -Z, r18 cpc r31, r25 brne .-8 где ((r31-r25) * 256) - размер массива
Сообщение отредактировал alexeyv - Jul 1 2011, 13:31
|
|
|
|
|
Jul 2 2011, 18:33
|
Местный
  
Группа: Участник
Сообщений: 245
Регистрация: 15-08-07
Пользователь №: 29 795

|
Цитата Необходимо снять лог некой шины, у которой частота в районе мегагерца. Наивный, однако После некоторых телодвижений - Mega162 была задвинута в сторонку. Еще после некоторых телодвижениий эйфории от юзания XMega тоже поубавилось. В конечном итоге, в ходе издевательств над собой и процом, оказалось, что Мега, погнанная до 48Мгц с четырьмя тактами на одно измерение, судя по всему, не отражает достоверно состояние шины т.к. есть одиночные показания некоторых бит. Стало быть, есть вероятность, что какие-нибудь данные могут проскочить мимо. Что-ж, видать, не судьба. Есть предположение, что DMA не сумеет опросить порты быстрее, чем есть на данный момент. В любом случае, на данный момент я не смог найти, как прикрутить DMA к портам. Исходник приложу - вдруг какие-нибудь мысли появятся. CODE typedef unsigned char u08; typedef unsigned int u16; typedef unsigned long u32;
#define F_CPU 48000000UL
#include <avr/io.h> #include <util/delay.h>
#define USART USARTC0 #define OnLight PORTQ.OUTCLR = PIN2_bm #define OffLight PORTQ.OUTSET = PIN2_bm #define ToggleLight PORTQ.OUTTGL = PIN2_bm #define IsPressedButton (PORTQ.IN & PIN3_bm)
#define GetPortOne PORTK.IN #define GetPortSecond PORTK.IN
#define ScanPorts10(p) do{*p-- = GetPortOne; *p-- = GetPortSecond; /* 0 */\ *p-- = GetPortOne; *p-- = GetPortSecond; /* 1 */\ *p-- = GetPortOne; *p-- = GetPortSecond; /* 2 */\ *p-- = GetPortOne; *p-- = GetPortSecond; /* 3 */\ *p-- = GetPortOne; *p-- = GetPortSecond; /* 4 */\ *p-- = GetPortOne; *p-- = GetPortSecond; /* 5 */\ *p-- = GetPortOne; *p-- = GetPortSecond; /* 6 */\ *p-- = GetPortOne; *p-- = GetPortSecond; /* 7 */\ *p-- = GetPortOne; *p-- = GetPortSecond; /* 8 */\ *p-- = GetPortOne; *p-- = GetPortSecond; /* 9 */}while(0)
#define ScanPorts100(p) do{ScanPorts10(p); /* 0 */\ ScanPorts10(p); /* 1 */\ ScanPorts10(p); /* 2 */\ ScanPorts10(p); /* 3 */\ ScanPorts10(p); /* 4 */\ ScanPorts10(p); /* 5 */\ ScanPorts10(p); /* 6 */\ ScanPorts10(p); /* 7 */\ ScanPorts10(p); /* 8 */\ ScanPorts10(p); /* 9 */}while(0)
#define ScanPorts1000(p) do{ScanPorts100(p); /* 0 */\ ScanPorts100(p); /* 1 */\ ScanPorts100(p); /* 2 */\ ScanPorts100(p); /* 3 */\ ScanPorts100(p); /* 4 */\ ScanPorts100(p); /* 5 */\ ScanPorts100(p); /* 6 */\ ScanPorts100(p); /* 7 */\ ScanPorts100(p); /* 8 */\ ScanPorts100(p); /* 9 */}while(0)
#define PutChar(ch) do{}while(!(USART.STATUS & USART_DREIF_bm));\ USART.DATA = ch;
#define SIZE_ARRAY 8000 unsigned char array[SIZE_ARRAY];
void sendDigit(u16 digit){ PutChar(digit/1000 + '0'); digit %= 1000; PutChar(digit/100 + '0'); digit %= 100; PutChar(digit/10 + '0'); digit %= 10; PutChar(digit + '0'); PutChar(' '); PutChar(' '); }
void sendBusState(u08 state){ for(u08 i=0; i<8; ++i){ PutChar(state & _BV(7) ? '1' : '0'); PutChar('\t'); state <<= 1; } }
int main(void){ OSC.XOSCCTRL=0x4b; // диапазон: 2-9 МГц, внешний резонатор, с временем запуска 16 000 циклов OSC.CTRL=0x08; // включаем генератор на внешнем кварцевом резонаторе while(!(OSC.STATUS&0x08)); // ждём готовности генератора на внешнем кварцевом резонаторе
OSC.PLLCTRL=0xc6; // внешний источник синхро, множитель=6 OSC.CTRL=0x18; // включаем синтезатор частоты while(!(OSC.STATUS&0x10)); // ждём готовности синтезатора частоты
CPU_CCP=0xd8; // разрешить (сигнатурой) изменение важного регистра (следущая строка) CLK.CTRL=0x04; // источник системной синхронизации - синтезатор частоты CLK.PSCTRL=0x00; // Коэф. деления предделителей A, B и C = 1.
PORTC.DIRSET = PIN3_bm; PORTC.DIRCLR = PIN2_bm;
USART.CTRLC = (uint8_t) USART_CHSIZE_8BIT_gc | USART_PMODE_DISABLED_gc; USART.BAUDCTRLA = (u08)289; // Битрейт 921600 при 48МГц clock USART.BAUDCTRLB = (289 >> 8) | ((-7) << USART_BSCALE0_bp); USART.CTRLB |= USART_TXEN_bm;
PORTQ.DIRSET = PIN2_bm; // PQ2 Лампа PORTQ.DIRCLR = PIN3_bm; // PQ3 Кнопка PORTQ.PIN3CTRL = PORT_OPC_WIREDORPULL_gc; // Подтяжка вниз
PORTK.DIR = PORTJ.DIR = 0; PORTJ.PIN0CTRL = PORTJ.PIN1CTRL = PORTJ.PIN2CTRL = PORTJ.PIN3CTRL = PORTJ.PIN4CTRL = PORTJ.PIN5CTRL = PORTJ.PIN6CTRL = PORTJ.PIN7CTRL = PORTK.PIN0CTRL = PORTK.PIN1CTRL = PORTK.PIN2CTRL = PORTK.PIN3CTRL = PORTK.PIN4CTRL = PORTK.PIN5CTRL = PORTK.PIN6CTRL = PORTK.PIN7CTRL = PORT_OPC_WIREDANDPULL_gc; // Подтяжка вверх
while(1){
while(!IsPressedButton){ _delay_ms(250); ToggleLight; }
u08 *p = &array[SIZE_ARRAY-1];
while(!(PORTJ.IN & PIN7_bm)); // Ждать появления питания на девайсе
ScanPorts1000(p); ScanPorts1000(p); ScanPorts1000(p); ScanPorts1000(p);
p = &array[SIZE_ARRAY-1]; u16 index = SIZE_ARRAY-1;
PutChar('-'); PutChar('-'); PutChar('-'); PutChar('-'); static u16 currentSample = 0; sendDigit(currentSample++); PutChar('\n'); PutChar('\r');
do{ sendDigit(index--); PutChar('\t');
//sendBusState(*p--); //PutChar('\t');
sendBusState(*p); PutChar('\n'); PutChar('\r'); static u08 pause = 0; if(!pause--) _delay_ms(10); // Для компенсации "несинхронности UART" }while(p-- != array);
PutChar('\n'); PutChar('\r'); PutChar('\n'); PutChar('\r'); PutChar('\n'); PutChar('\r');
_delay_ms(500); } }
Сообщение отредактировал IgorKossak - Jul 2 2011, 20:08
Причина редактирования: [codebox]
|
|
|
|
|
Jul 2 2011, 20:22
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(Sirko @ Jul 2 2011, 17:33)  Наивный, однако  Да, наивный и упрямый, поскольку, чтобы считать сигнал около мегагерца, нужна частота выборок около двух мегагерц. Следовательно, при тактовой частоте проца 20 МГц, необходимое число тактов на цикл 20/2=10 машинных циклов. Десяти циклов должно хватить за глаза. Скажу так, за 5 циклов можно считать из порта, записать в память, передвинуть указатель и проверить его на конец массива. Ну и ещё чего-нибудь, скажем помигать светодиодом и опросить кнопки. Ну или непрерывно писать в буфер циклически и по запросу выдавать весь массив, который записан на текущее время.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Jul 2 2011, 20:50
|
Местный
  
Группа: Участник
Сообщений: 245
Регистрация: 15-08-07
Пользователь №: 29 795

|
Цитата Скажу так, за 5 циклов можно считать, записать, передвинуть, проверить и ещё чего-нибудь Это че, - шутка юмора такая? Записать-передвинуть с проверкой менее шести тактов, - не представляю как. Или Вы имеете ввиду 5 команд процессора? Цитата чтобы считать сигнал около мегагерца, нужна частота выборок около двух Это никто не оспаривает. 1Мгц - было предположение, поскольку визуально дорожки длинные, несуразные, тянутся от основого чипа к другим - звездой, через разъемы на разные платы, плюс еще в настоящий момент соплей навешано (шлейф от флопика с макетками) и это все вроде как продолжает функционировать. На текущий момент у меня скан получается порядка 12МГц, но есть вероятность, что и этого недостаточно. Цитата нужно развернуть цикл и повторить 1000 раз фрагмент "прочитать порт в регистр + сохранить регистр с автоинкрементом". Вот вам три такта и будет У меня получается четыре . . . lds r24, 0x0728 sts 0x3F42, r24 lds r24, 0x0728 sts 0x3F41, r24 lds r24, 0x0728 sts 0x3F40, r24 . . .
Сообщение отредактировал Sirko - Jul 2 2011, 20:56
|
|
|
|
|
Jul 2 2011, 21:45
|
Гуру
     
Группа: Участник
Сообщений: 3 834
Регистрация: 14-06-06
Из: Moscow, Russia
Пользователь №: 18 047

|
Цитата(Sirko @ Jul 3 2011, 00:50)  Это че, - шутка юмора такая? Записать-передвинуть с проверкой менее шести тактов, - не представляю как. Или Вы имеете ввиду 5 команд процессора? Loop: in temp,<порт> st Z+,temp cp ZL,... cpc ZH,... in temp,<порт> st Z+,temp brne Loop
|
|
|
|
|
Jul 2 2011, 22:33
|
Местный
  
Группа: Участник
Сообщений: 245
Регистрация: 15-08-07
Пользователь №: 29 795

|
Попробую прокоментировать, если че поправьте.
Loop: in temp,<порт> - получить состояние шины (1 такт) st Z+,temp - засунуть это значение в оперативку (2 такта) cp ZL,... - если младший байт указателя не переходит границу, то перейти к опросу порта (1 такт) cpc ZH,... - иначе проверить старший байт, если ... - неважно in temp,<порт> - получить состояние шины (1 такт) st Z+,temp - засунуть это значение в оперативку (2 такта) brne Loop - продолжить (если нужно) (1 такт)
Т.е. если не придираться к иногда возникающему CP-CPC, то в среднем по четыре такта на один опрос. Ну в принципе в настоящий момент у меня тоже их четыре А вот как-бы засунуть в сишный файл вот это - in temp,<порт> st Z+,temp in temp,<порт> st Z+,temp in temp,<порт> st Z+,temp ... ???
|
|
|
|
|
Jul 3 2011, 07:11
|
Гуру
     
Группа: Участник
Сообщений: 3 834
Регистрация: 14-06-06
Из: Moscow, Russia
Пользователь №: 18 047

|
Цитата(Sirko @ Jul 3 2011, 02:33)  Попробую прокоментировать, если че поправьте.
cp ZL,... - если младший байт указателя не переходит границу, то перейти к опросу порта (1 такт) Вот тут неправильно. Последовательность cp ZL,... cpc ZH,... - это сравнение с 16-битным значением (заданным в регистрах), определяющим границу массива. Цитата Т.е. если не придираться к иногда возникающему CP-CPC, то в среднем по четыре такта на один опрос. Не четыре, а пять, и не в среднем, а всегда. Но граница должна быть установлена на один байт раньше.
|
|
|
|
|
Jul 3 2011, 07:58
|
Местный
  
Группа: Участник
Сообщений: 245
Регистрация: 15-08-07
Пользователь №: 29 795

|
Цитата Вот тут неправильно. Понял. Спасибо. Но тогда выходит, что Цитата и не в среднем, а всегда. - всегда, но чередуясь 5, 4, 5, 4, 5... Loop: in temp,<порт> - получить состояние шины (1 такт) st Z+,temp - засунуть это значение в оперативку (2 такта) cp ZL,... - если младший и cpc ZH,... - старший байт указателя переходят границу - выставить флаг (2 такта) in temp,<порт> - получить состояние шины (1 такт) st Z+,temp - засунуть это значение в оперативку (2 такта) brne Loop - продолжить (если нужно) (1 такт)
|
|
|
|
|
Jul 4 2011, 13:25
|

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

|
Цитата(Sirko @ Jul 3 2011, 12:51)  Спасибо, буду знать. Эта задача не для AVR. Возьмите простенький CPLD + static RAM + mega162. подключите CPLD и мегу(по ее шине) к МС памяти. Внутри CPLD организуется счетчик по отрицательному фронту строба шины которую хотите мониторить. По стробу внешней шины читайте с нее данные и кладите в SRAM. при переполнении счетчика, отключите CPLD от памяти и дайте меге строб что та может читать. CPLD на 150-180Mhz с требуемым количеством ног (вам надо 18+8+2) стоит в районе 5$-8$. либо готовая макетка за 13$ здесьМС SRAM брать такую чтобы успевала за шиной которую собрались мониторить. В старых 386-х под кеш использовались 10нс (100Mhz) память 62256 (32KB чип) в DIP копусах вот ее можно взять, но возможно хватит и более медленной памяти.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|