Обзор клона меги328 -LGT8F328P

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

Купил поизучать що це таке вот такую платку а-ля Nano от небезызвестного китайского завода WAVGAT

На самом МК маркировка как и на картинке - WAVGAT AVGA328P, а фактически там стоит МК LGT8F328P от компании LogicGreen, об этом говорит хотя бы аддон, который продавец  рекомендует установить. Кстати продавец честно пишет, что это нано-совместимая плата.   В принципе об этом МК уже неоднократно писали, но информация неполная, а местами даже недостоверная. Так что решил что будет лучше собрать всё в одном месте. Подобные ардуины кстати делают так-же и другие производители, так что в целом всё будут справедливо и для других вариаций, типа промини WemosXI и прочих.

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

И так, принципиальные отличия от меги 328:
-поддерживаются тактовые частоты до 32МГц как от внутреннего PLL-синтезатора, так и от внешнего кварца или кварцевого генератора.

-питание 1.8-5.5 вольт, причём 1.8 вольт поддерживается даже на самой высокой частоте.

-у этого МК нет фьюзов, любые параметры, аналогичные тем, что настраиваются в меге328 фьюзами можно настроить или изменить прямо из программы.
-Что-бы МК поддерживал ардуино на стандартной частоте 16Мгц регистр управления системными клоками настраивается в бутлоадере.
-Поэтому не смотря на то, что там залит стандартный оптибутовский бутлоадер -с другими ардуиновскими лоадерами он не совместим, так как адаптирован под данный МК. Если залить обычный бутлоадер от меги, то пологаю МК может и запуститься, но на какой-то дефолтовой частоте.
- На конкретно моей плате ещё стоят 2 кварца на 12МГц (для CH340 и для МК). Причём для МК он по умолчанию не используется, т.к. бутлоадер настраивает системные клоки на внутренний генератор 32МГц с делителем 2, т.е. так получаются заветные 16МГц.
Из первых разочарований -внутренний генератор не смотря на то, что довольно точный (заявлена 1% точность) - но по сути всё равно паршивый, у него жуткий джиттер. Включаю вывод тактовой на ногу PB0

CLKPR = 1<<PMCE;//разрешить изменение
CLKPR = 1<<5 | 1<<0; //делитель =2 и вывод clk

И смотрю осциллом:

А вот какая картинка, если переключится на кварц:

sysClock(EXT_OSC);
CLKPR = 1<<PMCE;//разрешить изменение 
CLKPR = 1<<5; // вывод clk

Гораздо лучше, хотя всё равно небольшой джиттер есть, но что его производит не могу понять, видимо кварц на борту тоже не высокого качества.

Затактировал от внешнего генератора 32MHz

#include "lgtx8p.h"
int main(){
PMCR=1<<PMCE; //разрешить выбор источника тактирования
PMCR= 1<<2 | 1<<5; //External high frequency crystal 
PMX2= 1<<WCE;//разрешить изменения
PMX2= 1<<XIEN;//разрешить вход тактовой частоты от кварц. генератора
CLKPR = 1<<PMCE;//разрешить изменение
CLKPR = 1<<5; //делитель =1 и вывод clk
}

Совершенно другое дело, сигнал с той же ноги:

-ещё  WatchDog тут умеет тактироваться как от своего, так и от системного rc-осциллятора. Т.е. должен быть гораздо точнее во втором случае.

- Таймеры. В сравнении с мегой328 добавился 16-битный таймер3. Обладает всеми возможностями 1-го, но имеет доп. регистры. Аппаратных ног у третьего таймера как и у остальных таймеров (в 32х выводном МК) тоже две-  OCR3A/B , которые доступны на арду-пинах TXd и D2.  Соответссно всего на плате имеется 8 ног с PWM.  Таймеры 0 , 1  могут тактироваться от внутреннего PLL синтезатора 64МГц. Соответственно умеют шиммить на гораздо более высоких частотах чем мега328. Так же 0 , 1 и 3  таймеры умеют делать дид-тайм, и у них есть возможность отключать свои выходы по всяким событиям (срабатывание компаратора, внешнее прерывание, переполнение от другого таймера).

- ЦАП имеется в количестве 1 штука, 8-битный.  Может брать референс от Vcc или от внутренних источников.   Вывел пилу для визуальной оценки:

#include "lgtx8p.h"
 void setup() {
DACON= 1<<DACEN | 1<<DAOE ; // dac-on, включить пин
static uint8_t n=0;
cli();
while(1){  DAL0=n++;  } 
}
 
void loop() {}

Сперва что-то не пошло, выдавало кривую пилу. Со второго захода вроде нормально стало.

Но есть нюанс,- у этого ЦАПа выход с каким-то большим внутренним сопротивлением, попробовал подключил киломный резюк -сигнал схлопнулся почти что в ноль. Так что без  ОУ этот ЦАП не стоит использовать. Судя по этому, а так же по высокой скорости работы и по картинке в даташите -цап чисто резисторный :)

-Компаратор (2 штуки) тут гораздо более продвинутый. Есть возможность использовать DAC как один из входов. Или любое из калиброванных внутренних референсных напряжений (а их тут 3 - 1.024V, 2.048V и 4.096V)   А главное, чего не было в меге -тут есть гистерезис! 

-АЦП -12 битный, есть возможность дифф.включения входов и  усиления входного сигнала в 8/16/32 раз. Доступны любые референсы, в том числе от ЦАПа.   АЦП этот бегло протестировал, не очень впечатляет. Возможно это недостаток платы , на которой припаян МК, но 12-битного разрешения мне не удалось выжать даже при идеальном источнике сигнала и референса, 10 бит пожалуй  будет, но с программным усреднением: при референсе 2,048V удалось добиться гуляние результата оцифровки измерения напряжения батарейки   +/-  1mV

-Порты здесь  рассчитаны в основном на 30мА нагрузки. Но есть некоторые у которых ток по умолчанию лишь 12 мА, но через регистр HDR (high-current push-pull) можно включить буффер, и  максимальная нагрузка на них возрастает до 80мА. Но таких портов немного, (PE5) (PE4) (PD2)  (PD1) (PD6)  (PD5)       

-Есть ещё интересные регистры мультиплексирования - с помощью них можно перекинуть некоторые сигналы таймеров или сериала на альтернативные ноги. Есть даже возможность переназначить ногу AREF как порт PE6 , и даже ресет в порт  PC6 .

Пример задействования ног  SWC,SWD,ADC6,ADC7,AREF - их можно сделать выходами порта E

#include "lgtx8p.h"
void setup() {
PMX2= 1<<WCE;
PMX2= 1<<E6EN; //сделеть AREF ногой PE6
MCUSR&= ~(1<<7);
MCUSR|= 1<<7;// Освободить PE0,PE2 от SWD
//ноги SWC=PE0,ADC6=PE1,SWD=PE2, ADC7=PE3,AREF=PE6
DDRE= 1<<0 | 1<<1 | 1<<2 | 1<<3 | 1<<6 ; 

Пример ногодрыга с переключением клоков на  тактовую 32МГц.

int main(){
CLKPR = 1<<PMCE;//разрешить изменение
CLKPR = 0; //делитель =1
DDRB = 1<<4; // 12 пин OUTPUT
 while (1){ PINB=0x10; }
}

Как видно полный цикл ногодрыга получится  из 4х тактов МК (инверсия ноги, jamp, инверсия ноги, jamp) Поэтому на выходе меандр с частотой 8 МГц.  (32/4)

-Дополнил распиновку модуля теми сигналами, что не были указаны. Так же исправил несколько ошибок на исходной картинке.

-Документация  оригинальный даташит на МК на китайском, есть так же его переведённая на инглиш гуглом версия, но там убились все картинки и сбился формат строк. Наш коллега Green  нашёл  русскоязычный даташит LGT8F328P datasheet  за что спасибо ему и большое спасибо автору перевода.  Даташит сам по себе не очень хороший, в нём например не все регистры описаны, которые есть в сводной таблице. Внимание, в даташите есть мелкие ошибки! Примеры приводить не буду, что б не раздувать пост. 

Так же переведён на русский даташит на более старую модель МК  LGT8F328D, в нём максимальная частота 20МГц, нет третьего таймера, но зато вроде как есть два ЦАПа. Предположительно он ставился в платы MassDuino и WEMOS XI. Определить какой у вас МК пологаю можно запрограммировав 3й таймер. Его можно запустить даже без аддона, я указал для таймера прямые адреса без дефайнов)

//Тест на наличие таймера3 -при 16МГц тактовой светодиод Тх замигает с частотой примерно 5Герц
void setup() {
*(uint8_t*)0x33 =0x2 ;//  DDRF=1<<DDF1
*(uint8_t*)0x99 =0x5; // OCR3AH=0x5;
*(uint8_t*)0x98 =0xDC; // OCR3AL=0xDC;
*(uint8_t*)0x90 =0x40; // TCCR3A=1<<COM3A0;
*(uint8_t*)0x91 =0xD;  // TCCR3B=1<<WGM32 | 1<<CS30 |1<<CS32;
}
void loop(){}

-Аддон (пакет поддержки мк) для Arduino IDE лучше брать не тот, который со страницы продавца, а родной, от производителя контроллера. С ним меньше проблем.

-прошивка производится либо через бутлоадер , либо специальным  программатором через serial wire debug (SWD) interface по двум проводам. К счастью добрые люди уже написали скетч для ардуины, которая превращается в SWD программатор.  Дополнение: к сожалению этот скетч только для МК LGT8F328D , c *P он не работает.

Напоследок табличка, где сравнивается скорость выполнения  в тактах некоторых ассемблерных команд в обычном AVR и в LGT8

Instruction Function                    Cycle of AVR    Cycle of LGT8XM

ADIW        Add immediate to word       2               1
SBIW        Subtract immediate to word  2               1
MUL/S/SU    8bit multiply               2               1
FMUL/S/SU   Fractional multiply         2               1
RJMP/RCALL  Relative jump/call          2/3             1
IJMP/ICALL  Indirect jump/call          2/3             2
RET/IRET    Return                      4               2
CPSE        Compare, skip if equal      1/2/3           1/2
SBIS/SBRS   Skip if set                 1/2/3           1/2
SBIC/SBRC   Skip if cleared             1/2/3           1/2
LD/LDD      Load indirect               2               1
ST/STD      Store indirect              2               1
LPM         Load program memory         3               2
PUSH/POP    Stack access                2               1

 

Добавлено 25.07.2019

На этой плате неправильно разведён USART, специально срисовал схему для наглядности:


 

Как видно обмен данными возможен только между мк и usb-мостом. Какой-либо внешний сериальный сигнал подать нет возможности, он просто не прожмёт линию, которую каждый чип и светодиоды тянут вверх. Но выход есть, на помощь приходят регистры port multiplexing (PMX). Можно перенести Rx и Tx (оба одновременно или только какой то один ) на другие пины:

PMX0= 1<<7;//разрешить ремаппинг
PMX0= (1<<RXD5) |( 1<<TXD6) ; 

Так что подключить bluetooth/GPS не проблема.  Так же отремаппить можно и выход таймера OC3A, который сидит на пине Txd, и так же страдает от резистора.

На этом всё. Просьба не нажимать кнопку "цитировать", т.к. у меня пропадёт возможность что-то добавлять в этот пост.

semaawp
semaawp аватар
Offline
Зарегистрирован: 29.05.2017

Интересный камень, спасибо за информацию. Пойду добывать сведения про него

slider
Offline
Зарегистрирован: 17.06.2014

здоровские исследования.

порадовало -АЦП -12 битный, есть возможность усилить входной сигнал в 8/16/32 раз. (для измерений на шунтах само-то . и измерений с высокоомным входом , хотя для микропотребления, чтоб не заморачиваться с ключём для делителя , годно работал делитель 10МОм+1МОм || кондер керамика 0.1мкф 50в)

делителя нет у atmega328p .  хотя на меге2560 есть x200  http://arduino.ru/forum/apparatnye-voprosy/koeffitsient-usileniya-u-analogovogo-vkhoda .  и тиньках  x20  ( x200 )

так что там про 32МГц ? , очень интересно.  Какую частоту выдает ногодрыг? можно выдавить 32МГц (длину импульса 31нс, и сколько там будет период)?

как это было на atmega328 , длина импульса 62 нс , период=250мс => частота 4мгц ,:

1
2
3
4
5
6
7
8
9
10
11
12
13
void setup()
{
DDRB = B10000000; // устанавливаем 13 пин как OUTPUT
}
void loop()
{
// создаем свой бесконечный цикл
 while (1)
{
  PORTB = B10000000; // устанавливаем состояние pin13 как HIGH
  PORTB = B00000000; // устанавливаем состояние pin13 как LOW
}
}

взято здесь  http://robotosha.ru/arduino/digitalwrite-optimizing-arduino.html

 

// по идее можно было еще больше выдавить частоту чем 4мгц применив

RJMP/RCALL  Relative jump/call          2/3             1
// создаем свой бесконечный цикл
M1:
  PORTB = B10000000; // устанавливаем состояние pin13 как HIGH
  PORTB = B00000000; // устанавливаем состояние pin13 как LOW
goto M1;

 

 

 

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Спасибки, очень интересно.

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

slider, завтра проверю ногодрыг  на 32МГц, на ассемблере,  со счётом тактов, всё как пологается :)

slider
Offline
Зарегистрирован: 17.06.2014

------- 32 MГц  WAVGAT328  в  2.66 раза  оказался быстрее чем Atmega328p  !!!  ------

dimaxв принципе то вроде все сходится без написания на ассемблере.

1такт - лог.1

1такт - лог.0

1такт - переход rjmp в цикле на начало (у атмеги328 было значит 2 такта)

и того 32нс * 3 = 96.  

1000/96= 10.4  вот и получалось на выходе 10.5МГц     (на atmega328p было 4МГц 1такт+1такт+2такта переход)

Из фотки видать что лог.1=лог.0=rjmp= ~31нс , а это и есть 1 такт при 32МГц !!!

пулучается все верно , забираем у проца по 3 такта по кругу и получаем грубо частоту 32МГц/3  .

 

// фотки осциллограф sds1102cml не сохранят картинки на флэшку, а только файлы настроек *.set  ,в инете у когото чудесным образом получилось. я не знаю как заставить его сохранять.

slider
Offline
Зарегистрирован: 17.06.2014

dimax ,, переключи щуп осцила на делитель 10 , и тогда пила будет пила отличная !  (собственно осцилы портят и цифровые сигналы на 1 , поэтому иногда имеет смысл переключать на щупе на 10)

при вкл. на 32МГц

#include "lgtx8p.h"
 void setup() {
CLKPR = 1<<PMCE;//разрешить изменение
CLKPR = B00000000;

DACON= 1<<DACEN | 1<<DAOE ; // dac-on, включить пин
static uint8_t n=0;
cli();
while(1){  DAL0=n++;  } 
}
 
void loop() {}

частота повышается с 6.9КГц до 13.8КГц

пила тож норм. , также малехо также подрыгивается из-за плавания частоты внутреннего гена.

renoshnik
Offline
Зарегистрирован: 11.04.2013

Пробовали работать с ЕЕPROM - у меня библиотека глючит. Пишет, что она для архитектуры АВР .

slider
Offline
Зарегистрирован: 17.06.2014

renoshnik норм,  ничего не глючит (IDE 1.8.5) , запускаю из

C:\Users\.......\Documents\Arduino\WAWGAT\E2PROM\examples  (в мои доки скинул примеры и либу с гитхаба  https://drive.google.com/open?id=10gwrG9uTDwaEO-7EudsmBkfgdcyrcABI эта ссылка у продавца на али)

// полагаю что может ваше IDE из-за более близких к началу списка подтягивает оригинальную либу EEPROM.h . попробуйте закинуть либу в либы что в моих документах.  и мож в моих документах в скетчи закинуть.

//// и заметил разве что как-то в 0 адрес ничего не пишется , всегда там читается 0 , а в другие адреса и пишется всякое и читается верно. А потом в сетап поставил холостой  value = EEPROM.read(address);  и все норм читается из 0 адреса.

/*
 * EEPROM Read
 *
 * Reads the value of each byte of the EEPROM and prints it 
 * to the computer.
 * This example code is in the public domain.
 */

#include <EEPROM.h>

// start reading from the first byte (address 0) of the EEPROM
int address = 0;
byte value;

void setup()
{
  // initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
    
  }
 // delay(1000); // на всяк случай
   value = EEPROM.read(address); // холостой
}

void loop()
{
  // read a byte from the current address of the EEPROM
  value = EEPROM.read(address);
  
  Serial.print(address);
  Serial.print("\t");
  Serial.print(value, DEC);
  Serial.println();
  
  // advance to the next address of the EEPROM
  address = address + 1;
  
  // there are only 512 bytes of EEPROM, from 0 to 511, so if we're
  // on address 512, wrap around to address 0
  if (address == 512)
    address = 0;
    
  delay(50);
}

 

Green
Offline
Зарегистрирован: 01.10.2015

Уже где-то писал:
【重要说明】:  
LGT8FX8D 最高运行频率为20MHz,  因此当选择内部32MHz RC作为主时钟源时,一定要
保证CLKPR设置为正确的分频配置(最低2分频)。

dimax пишет:

-к сожалению оригинальный даташит на МК на китайском, есть так же его переведённая гуглом версия,

Есть на русском. Красивый, с цветными картинками). Уже не помню где брал.
 

renoshnik
Offline
Зарегистрирован: 11.04.2013

Про бутлоадер  https://www.drive2.ru/b/508852882896847017/

Игрался с АЦП  https://www.drive2.ru/b/506709110100590734/

 

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

Green, LGT8FX8D -это немножко другой МК, более старая модель. У них не очень значительные отличия, но одно из них как раз максимальная частота. По моему ещё математические 16-битные регистры и таймер3 тоже есть только в *P модели, и ещё из броского по даташитам - ЦАПов в *D было 2 штуки, а в *P оставили один. PS: думаю многие будут благодарны, если найдёте  даташит на русском, пусть даже более старой модели, всё равно пригодиться :)

slider, щуп на /10 переключал, при этом горб выпячивался в другом месте, я в реальности около часа пытал этот ЦАП, всё  что можно перепробывал, до конца надеялся, что можно что-то сделать, но увы.  Как вариант -может это просто бракованный мк, всякое бывает, тем более у таких левых производителей :)

Green
Offline
Зарегистрирован: 01.10.2015
alex_r61
Offline
Зарегистрирован: 20.06.2012

 

Война клонов?  Или китайцы выпустили один клон и тиражируют его

в разных вариантах. Давно купил MD-328D, но руки до него так и недошли.

Сейчас глянул доки, блок-схемы один в один. Только названия ядра разные и

некоторые другие отличия. У моего, например, АЦП 10/12/16 бит.

Сейчас глянул на их сайт, они новый клон запилили MD-3248P. И сделали на нём плату.

http://www.inhaos.com/product_info.php?products_id=168

Но ИМПЕРИЯ наносит ответный удар. http://www.microchip.com/promo/atmegaavr-family

Да, EEPROM у них нет. “ (simulate E2PROM) “ В флеше область выделяют.

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

Logik, сейчас проверил ссылка на продавца работает.. кликнул -открылась.

alex_r61, подозреваю, что Inhaos  как и WAVGAT крупный покупатель у ложик грина, и для них МК маркируют по-другому. За 16 бит АЦП там выдают оверсемплинг 12ти бит.

Logik
Offline
Зарегистрирован: 05.08.2014

dimax пишет:

Logik, сейчас проверил ссылка на продавца работает.. кликнул -открылась.

То известная багофича сайта. Вставте через кнопку "Вставить/редактировать ссылку". Хотя себе я уже нашел его https://ru.aliexpress.com/item/WAVGAT-Nano-Mini-USB-Nano-3-0/32868170637.html Закажу пожалуй.

А он чё, реально в коробочке приезжает? Там жеж одна коробочка этих денег стит ;) В половине случаев она за корпус прибора сойдет.

malser
Offline
Зарегистрирован: 12.09.2018
DIMAX 
Пытаюсь залить бутлоадер в платку WAWGAT. Взял скетч по вашей ссылке, скомпилировал и залил на Ардуино нано3. Подключил Wavgat. Нажимаю кнопку залить загрузчик - выдает следующее. Вы не пробовали заливать?
C:\Users\malserr\Downloads\arduino-1.8.6-windows\arduino-1.8.6\hardware\tools\avr/bin/avrdude -CC:\Users\malserr\Downloads\arduino-1.8.6-windows\arduino-1.8.6\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -carduino -PCOM5 -b19200 -Uflash:w:C:\Users\malserr\Downloads\arduino-1.8.6-windows\arduino-1.8.6\hardware\LGT\avr/bootloaders/lgt8fx8p/optiboot_lgt8f328p.hex:i 

avrdude: Version 6.3-20171130
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\malserr\Downloads\arduino-1.8.6-windows\arduino-1.8.6\hardware\tools\avr/etc/avrdude.conf"

         Using Port                    : COM5
         Using Programmer              : arduino
         Overriding Baud Rate          : 19200
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x15
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x15
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : Arduino
         Description     : Arduino

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x14

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x02

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x10
         Hardware Version: 4744608
         Firmware Version: 0.4611299
         Topcard         : STK502
         Vtarget         : 1.8 V
         Varef           : 0.0 V
         Oscillator      : Off
         SCK period      : 0.1 us

avrdude: stk500_initialize(): (b) protocol error, expect=0x10, resp=0x01
avrdude: initialization failed, rc=-1
         Double check connections and try again, or use -F to override
         this check.

avrdude: stk500_disable(): protocol error, expect=0x14, resp=0x10

avrdude done.  Thank you.

 

Logik
Offline
Зарегистрирован: 05.08.2014

В даташите с цветными картинками

[Важно] Максимальная рабочая частота LGT8FX8D составляет 20 МГц.
Поэтому, когда в качестве основного источника синхронизации выбран внутренний
32-мегагерцовый RC, необходимо убедиться, что CLKPR настроен на правильную
конфигурацию частотного разделения (минимум 2-х частотное деление).

Получается 32МГц официально нет?

slider
Offline
Зарегистрирован: 17.06.2014

Logik, читайте внимательней ,dimax выше писал что LGT8FX8D это немного другой по возможностям  чем LGT8F328P (AVGA328P) .
И в даташите  написали что 20мгц предел это только для LGT8FX8D, на LGT8F328P это ограничение не распространяется.

 

renoshnik
Offline
Зарегистрирован: 11.04.2013

malser пишет:

DIMAX 
Пытаюсь залить бутлоадер в платку WAWGAT. Взял скетч по вашей ссылке, скомпилировал и залил на Ардуино нано3. Подключил Wavgat. Нажимаю кнопку залить загрузчик - выдает следующее. Вы не пробовали заливать?
C:\Users\malserr\Downloads\arduino-1.8.6-windows\arduino-1.8.6\hardware\tools\avr/bin/avrdude -CC:\Users\malserr\Downloads\arduino-1.8.6-windows\arduino-1.8.6\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -carduino -PCOM5 -b19200 -Uflash:w:C:\Users\malserr\Downloads\arduino-1.8.6-windows\arduino-1.8.6\hardware\LGT\avr/bootloaders/lgt8fx8p/optiboot_lgt8f328p.hex:i 

avrdude: Version 6.3-20171130
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\malserr\Downloads\arduino-1.8.6-windows\arduino-1.8.6\hardware\tools\avr/etc/avrdude.conf"

         Using Port                    : COM5
         Using Programmer              : arduino
         Overriding Baud Rate          : 19200
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x15
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x15
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : Arduino
         Description     : Arduino

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x14

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x02

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x10
         Hardware Version: 4744608
         Firmware Version: 0.4611299
         Topcard         : STK502
         Vtarget         : 1.8 V
         Varef           : 0.0 V
         Oscillator      : Off
         SCK period      : 0.1 us

avrdude: stk500_initialize(): (b) protocol error, expect=0x10, resp=0x01
avrdude: initialization failed, rc=-1
         Double check connections and try again, or use -F to override
         this check.

avrdude: stk500_disable(): protocol error, expect=0x14, resp=0x10

avrdude done.  Thank you.

 

 

пост №15 про бутлоадер...

AleksandrGHJ
Offline
Зарегистрирован: 06.09.2018

Уважаемые Dimax и Logic, следуя вашим рекомендациям создам новую ветку с более подробным описанием. Вот только проведу дополнительные пробы, чтоб лишний раз не отвлекать по мелочам. Вдруг проблемы тут вовсе нет. Единственный вопросик: может раз уж у вас в руках имеются подобные девайсы может гляните у себя как ведет себя аналоговый вход?

Скеч предельно прост:

void setup() {
 Serial.begin(9600);
}
 
void loop() {
 Serial.println(analogRead(A1));
 delay(200);
}

Схему подключения можно также предельно упростить:

пробрасывать перемычкой на А1 напругу с пинов 5В; 3,3В и GND. У меня выдает в мониторе соответственно 2340, 4061, 0. хотя по логике вещей должно быть 4096, 2703 и 0.

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

Обновил первый пост:

- добавил осцилограмму с ноги D8 при тактировании от внешнего генератора + команды переключения
- c ЦАПа снял нормальную  осцилограмму другим щупом, поменял картинку.
- пример и осцилограмма ногодрыга на тактовой 32МГц -> 8МГц
-ссылки на руские даташиты
-тест на наличие таймера3
 

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

AleksandrGHJ, загрузил ваш скетч, подключил переменник 10 кОм -у меня всё линейно регулируется. Отдельно от 3.3 вольта показывает  3100 попугаев, от  5 вольт - 3968 попугаев. Тут наверное вам стоит обратить внимание на то, что это _нано_, у неё питание идёт через диод. В результате на Vcc приходит (на моей плате) 4,65в. И 3,3 у меня тоже не соответствует -реально 3,63. Если всё это пересчитать -то именно так и должно быть.

А 4095 в максимуме тут  быть не обязано, т.к. функция analogRead в этом аддоне навороченная, и делает калибровку смещения АЦП (страница 251 русского даташита), так что в моём случае АЦП откалибровалось с потолком 3968. В вашем -4061. Можете проверить чтение без арудиновских причуд моим скетчем, там будет  0..4095. Сигнал подавать на вход A0:

void setup() {
Serial.begin(9600);
ADCSRA|=1<<ADEN | 1<<ADPS2 |1<<ADPS1 |1<<ADPS0; // clk/128
ADCSRB=0; DIDR0=1<<0;
ADMUX=1<<REFS0; // ADC0 , AREF=Vcc
}

void loop() {
ADCSRA|=1<<ADSC;
while (bit_is_set(ADCSRA, ADSC));
uint16_t aread = ADC;
Serial.println(aread);
delay(100);

}

 

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

dimax, Какова максимально возможная скорость работы АЦП, можете измерить? Какой минимальный делитель тянет АЦП, пусть с потерей разрядности..

alex_r61
Offline
Зарегистрирован: 20.06.2012

 Какая максимальная частота у SPI. Ждёмс конкретных результатов работы с LCD TFT.

malser
Offline
Зарегистрирован: 12.09.2018

Кто-то загружал бутлоадер в эту плату?

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

Arhat109-2 пишет:

dimax, Какова максимально возможная скорость работы АЦП, можете измерить? Какой минимальный делитель тянет АЦП, пусть с потерей разрядности..

Даташит говорит, что больше 3МГц разрешение будет падать.  Проверил минимум -делитель на 2 держит однако, т.е. 8 МГц тактовую. Ну и 15 тактов на преобразование. 0,125µS * 15 = 1,875 µS. Не помню уж сколько у простой меги было. Для проверки завернул сигнал-треугольник  с выхода  ЦАПа через ОУ на вход АЦП, картинку рисует приемлемую.

Но с дефолтовым делителем более ровно рисует.

#include "lgtx8p.h"
uint8_t n;
void setup() {
Serial.begin(2000000);
DACON= 1<<DACEN | 1<<DAOE; // dac-on, включить пин
ADCSRA=1<<ADEN ; // clk/2
ADCSRB=0; ADCSRC=0;
ADMUX=1<<REFS0; // ADC0 , AREF=avcc
DIDR0=1<<0;
}

void loop() {
static bool dir=1;
DAL0= dir? n++ : n-- ;
if (n==255|| n==0) dir=!dir;
ADCSRA|=1<<ADSC;
while (bit_is_set(ADCSRA, ADSC));
uint16_t aread = ADC;
Serial.println(aread);
delay(5);

}

alex_r61 пишет:

 Какая максимальная частота у SPI. Ждёмс конкретных результатов работы с LCD TFT.

Если вопрос ко мне, то у меня не было планов подключать LCD..

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013

А как он по совместимости с Atmega328 на уровне регистров? Хотябы обратной?
 

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

sav13, я каждый регистр не сверял :)  думаю обратно совместимы, хотя какие-то нюансы скорее всего есть.  

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Уже нефигово. А с 32Мгц тактовой делитель на 2 - держит? (16Мгц частота Ацп)? У него 15 тактов преобразование? Впрочем, если 12 бит, то должно быть так, пасибки.

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

Arhat109-2, на 32х МГц тоже завелось, но картинка уж совсем непривлекательна..

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Ну .. непривлекательность картинки для меня - явление условное. А вот делитель 2 с 32метров .. это очень даже круто - практическая скорость оцифровки за мегагерц. :) На 8Мгц блока АЦП у Меги она ещё больше "непривлекательна", промежду прочим и ещё и не каждая мега такое может (328-я к примеру нет) .. там ваще рабочих макс. 6 разрядов и это при низкоомном выходе (как у Вас с ОУ) и правильной разводке ножек АЦП.. а в типовых платат так и ваще 5 бит. :)

P.S. на этом уже вполне можно лепить следящую систему за десятком целей.. :)

.. очень интересная машинка. Правда помнится микрочип тоже грозился выпустить обновление линеек, не знаю как там у них с этим - пошли или нет, не следил.

AleksandrGHJ
Offline
Зарегистрирован: 06.09.2018
dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

Всякие полезняшки:

Аналог "секретного вольтметра" для lgt8f328p  Измеряется напряжение на шине Vcc. Теория метода та-же самая, что и для меги 328. Ставится референс =AVCC, вход АЦП мультиплексором переключается на внутреннее, заведомо известное опорное напряжение (в данном случае 2,048 V). Затем через опорное вычисляется какое же было референсное. Ну тут я ещё усреднение добавил.

#include "lgtx8p.h"
void setup() {
Serial.begin(9600);
}

void loop() {
Serial.print(" Vbg,mV=");
Serial.println(Vbg());
delay(300);

}



uint16_t Vbg(){
ADCSRB=0;
ADCSRC=0;
ADCSRA=1<<ADEN | 1<<ADPS2 |1<<ADPS1 |1<<ADPS0; // adc enable , clk/128
ADMUX=1<<REFS0 | 1<<3 | 1<<2 | 1<<0; //ref=avcc, input= ivref 
ADCSRD=1<<BGEN | 1<<IVSEL0; //ivref=2048
VCAL=VCAL2;//load 2048 calibrate byte
uint32_t bgaread=0;
//собрать 256 семплов для усреднения
for (int n=0x0; n<=0xff; n++ ) {
  ADCSRA |= (1<<ADSC);   
    while (bit_is_set(ADCSRA,ADSC));
      bgaread += ADC;
        }
bgaread>>=8; 
bgaread= ((uint32_t)2048<<12) / bgaread;
return (uint16_t)bgaread;

  
  }

Следующий скетч  поочерёдно выводит внутренние референсные напряжения на вывод AVREF. Можно проконтролировать их точным вольтметром, и например учесть в расчётах. Или подкрутить заводские калибровочные константы VCAL*

#include "lgtx8p.h"
void setup() {
Serial.begin(57600);
ADCSRA|=1<<ADEN | 1<<ADPS2 |1<<ADPS1 |1<<ADPS0; // clk/128
ADCSRB=0;
ADMUX=0xd;     // ivref
ADCSRC=1<<0;
DIDR1=1<<PE6D;
}

void loop() {
Serial.println("Set AREF pin -> 4,096v");
ADCSRD=1<<BGEN | 1<<IVSEL1;
VCAL=VCAL3;
mydelay();
Serial.println("Set AREF pin -> 2,048v");
ADCSRD=1<<BGEN | 1<<IVSEL0;
VCAL=VCAL2;
mydelay();
Serial.println("Set AREF pin -> 1,024v");
ADCSRD=1<<BGEN;
VCAL=VCAL1;
mydelay();
}

void mydelay(){
for (byte n=0; n<=5; n++ ) {Serial.print("."); delay(1000); }
 Serial.println();
}

 

slider
Offline
Зарегистрирован: 17.06.2014

dimax ,     чутка не по теме, но как тож развитие atmega328, не посматривал ли такие контроллеры  ATxmega32D4  ?https://ru.aliexpress.com/item/-/32843431511.html
 по деньгам рядом с atmega328p(b)-au   , зато тож всяких возможностей гораздо прибавилось.  ATXMEGA32A4  еще покруче , но и подороже https://ru.aliexpress.com/item/10pcs-ATXMELA32A4-AU-ATXMEGA32A4-QFP-sold-together-new/32800983407.html  . мож потом кто и поддержку в IDE придумает.  

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

slider, не, семейством xMega вообще не интересовался. Психологически я уже перешёл на stm32, и другие МК меня не интересуют. Данный МК, которому посвящена тема исключение, заинтересовало что у любимой "тёплой, ламповой" меги328 появился братик со сверхспособностями, и его захотелось изучить :)

 

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

У xMega несколько странноватый способ прошивки, поэтому она не получила большого развития, ну и цена тоже "не айс". Хотя, когда ковырял даташит, была мысля что можно запилить обыкновенный USB-UART программатор, но так и не удалось найти камни по вменяемым ценам на тот момент.

slider
Offline
Зарегистрирован: 17.06.2014

Очень ясно. Вопрос закрыт.

А есть на памяти какой скетч тестовый арифметический ?, попробую от внешних активных кварцев погонять wavgat328 , интересно до какой частоты он стабильно может работать , 40 , 50мгц ? (Скетч , что сбои давал при разгоне)
Конечно такие опыты от лукавого , если надо быстрее - бери проц другой . но все таки хотелось бы проверить запас у него по частоте.

Logik
Offline
Зарегистрирован: 05.08.2014

Наверно БПФ посчитать подойдет. И познавательно будет.

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

Ещё в копилку полезняшек, этот МК обладает глобальным уникальным идентификационным номером. (GUID) Можно в чём-то это использовать, например привязать программу к этому номеру, и на другом МК она уже не заработает. Скетчик , считывающий GUID сначала заприметил на китайском сайте, но ещё при первом взгляде зародились сомнения, что правильно он работать не сможет. И точно, проверил -выдаёт только часть номера, думаю знающие люди сразу поймут почему. А незнающим хорошая задачка на самостоятельный разбор причины ;) Предлагаю другой вариант чтения GUID, без всяких байтовых сдвигов.


void setup() {
Serial.begin(9600);
uint32_t guid= *(uint32_t*)&GUID0 ;
Serial.println(guid,HEX); 
}

void loop() {}

 

slider
Offline
Зарегистрирован: 17.06.2014

dimax , гениально. китайцы до этого не додумались :)
хорошая плюшка.

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

Есть ещё в этом МК такая любопытная штука, как цифровой вычислительный ускоритель (uDSC).  Позволяет производить массу различный операций с целочисленными 16-битными числами  (кроме вычислений с плавующей точкой). Ускорение достигается за счёт того, что этот модуль любую операцию выполняет всего за 1 такт МК, правда тут возникают накладные расходы времени что-бы загрузить и выгрузить данные. Но загрузка и выгрузка каждого 16-разрядного слова тоже занимает 1 такт.  Выгружается кстати в 32-битный регистр (за 2 такта), так же есть ещё 16-битный регистр переполнения. Так что в теории можно производить операции с числами до 40 бит. Жалко что входные регистры не 32-битные, а то можно было бы посоревноваться с 72х мегагерцовым stm32 . Из-за специфики доступа к этому модулю компилятор понятия не имеет что он существует, поэтому что бы задействовать все эти способности нужно написать свою  функцию. Опять же из-за особенностей доступа к портам ускорителя напрямую  языком СИ невозможно к ним обратится. Я написал простую функцию на ассемблере, они принимает 3 операнда - первые два -это числа для ариф. операции, и третий операнд - код арифметической операции (подробности смотреть в русском даташите, страница36 )

void setup(){
Serial.begin(115200);
Serial.println ("Start..");
uint16_t a=16173, b=7522;
uint32_t data  = uDSC(a,b, 0x44);
Serial.print("a= "); Serial.print(a);
Serial.print("  b= "); Serial.println(b);
Serial.print("a * b = "); Serial.println (data); 
}
uint32_t uDSC(uint16_t dx, uint16_t dy, uint8_t opcode){
asm volatile(  
"ldi r18, 0x80;"     "\n\t" // byte  for DSUEN
"out 0x00, r18;"     "\n\t" // DCSR= 1<<DSUEN
"out 0x10, %[dsdx];" "\n\t" // DSDX = dx 
"out 0x11, %[dsdy];" "\n\t" // DSDY = dy 
"out 0x01, %[opc];"  "\n\t" // DSIR= operation code
"in r22, 0x38;"      "\n\t" // DSAL return 
"in r24, 0x39;"      "\n\t" // DSAH return
: : [dsdx] "r" (dx), [dsdy] "r" (dy), [opc] "r" (opcode)
) ; }

void loop(){}

 

Ну и естессно захотелось сравнить реально ли оно быстрее обычных вычислений? Проверка скорости дело не такое простое как может показаться на первый взгляд, компилятор может взять, и полностью изменить код.  Поэтому надо не давать ему такой возможности, но при этом сильно не мудря, что-бы посторонними операциями мк занимался минимальное время. Я решил умножать счётные регистры таймеров. 

/*тестирование скорости математическогго ускорителя LGT8F328P
данные для ариф. операций берутся от счётных регистров 3 и 2 таймера.
Счёт времени ведёт первый таймер. Программа выводит скорость подсчёта
функций, кол-во циклов в измерении  задано в дефайне cycles
*/
#define cycles 100 
#define tcnt2 (*(volatile uint16_t*)0xB1)
#define tcnt3 (*(volatile uint16_t*)0x94)
#include "lgtx8p.h"
uint16_t n; //
uint32_t data; //для результата ариф. операций

void setup(){
Serial.begin(115200);
Serial.println ("Start..");
TCCR2A=0;TCCR2B=1<<CS20; //запустить таймер
TCCR3A=0;TCCR3B=1<<CS30; //запустить таймер
TCKSR=0; TIMSK1=0; TCCR1A=0; TCCR1B=0; //обнулить лишнее
OCR1A=65535u; OCR1B=65535u;// чтоб удобнее читать регистр флагов

//Тестирование скорости операций DA=DA+(DX*DY) через uDSC
cli();
n=cycles;
TCNT1=0; TIFR1=TIFR1;
TCCR1B=1<<CS10;//подсчёт времени включён
while(n--) {
data  = uDSC(tcnt2,tcnt3); 
}
TCCR1B=0; sei();
Serial.print("Test uDSC  ");
if (TIFR1) {Serial.println("Timer overload");} 
  else Serial.print((float)TCNT1/16); Serial.println("  uS"); 

//Тестирование скорости операций DA=DA+(DX*DY) обычным способом 
data=0;
cli();
n=cycles;
TCNT1=0; TIFR1=TIFR1;
TCCR1B=1<<CS10;
while(n--) {
no_acsl(tcnt2, tcnt3);
}
TCCR1B=0;  sei();
Serial.print("Test Normal  ");
if (TIFR1) {Serial.println("Timer overload");} 
  else Serial.print((float)TCNT1/16); Serial.println("  uS"); 

}

void loop(){}

uint32_t no_acsl(uint16_t a, uint16_t b){
data+= (uint32_t)a * b;  
}

uint32_t uDSC(uint16_t dx, uint16_t dy){
asm volatile(  
"ldi r18, 0x80;"     "\n\t" // byte  for DSUEN
"out 0x00, r18;"     "\n\t" // DCSR= 1<<DSUEN
"out 0x10, %[dsdx];" "\n\t" // DSDX = dx 
"out 0x11, %[dsdy];" "\n\t" // DSDY = dy 
"out 0x01, %[opc];"  "\n\t" // DSIR= operation code
"in r22, 0x38;"      "\n\t" // DSAL return 
"in r24, 0x39;"      "\n\t" // DSAH return
: : [dsdx] "r" (dx), [dsdy] "r" (dy), [opc] "r" (0x47)
) ; }

Уж не знаю, оптимальный ли это код для тестирования. Я старался создать одинаковые условия. И обычный счёт и счёт через ускоритель вывел в отдельные функции, которые получали по два 16 бит операнда, а возвращали один 32 бит. Время считает таймер1, у микроса точность гораздо хуже. Результат такой, -на 100 циклах операции DA = DA + (DX*DY)  вывелось следущее:

Test uDSC  269.75  uS
Test Normal  451.00  uS

То есть с ускорителем в 1,5 раза быстрее. Ну если вычисление обычным способом убрать из отдельной функции и вставить в тело основной программы то результат сравнится. Но возможно, что все эти результаты полная фигня из-за того что я выбрал неудачно счётную задачу. Возможно в какой-то другой ситуации, где идёт какой-то входящий поток данных ускоритель даст в разы большую скорость. Интересно протестировать на FFT. Я за это пожалуй уже не возьмусь, и так времени целый день убил.

 

 

Logik
Offline
Зарегистрирован: 05.08.2014

Реальная круть! Прямо целый DSP! И то что на входе всего 16-бит нормально, даже правильно. Если не тяжело, прогоните тест еще например на 200 циклах, чтоб исключить потери времени на организацию цикла и т.д.

Хотя даже лучше просто продублировать строки 60-62. Типа так.

uint32_t uDSC(uint16_t dx, uint16_t dy){
asm volatile(  
"ldi r18, 0x80;"     "\n\t" // byte  for DSUEN
"out 0x00, r18;"     "\n\t" // DCSR= 1<<DSUEN
"out 0x10, %[dsdx];" "\n\t" // DSDX = dx 
"out 0x11, %[dsdy];" "\n\t" // DSDY = dy 
"out 0x01, %[opc];"  "\n\t" // DSIR= operation code
"out 0x10, %[dsdx];" "\n\t" // DSDX = dx 
"out 0x11, %[dsdy];" "\n\t" // DSDY = dy 
"out 0x01, %[opc];"  "\n\t" // DSIR= operation code
"in r22, 0x38;"      "\n\t" // DSAL return 
"in r24, 0x39;"      "\n\t" // DSAH return
: : [dsdx] "r" (dx), [dsdy] "r" (dy), [opc] "r" (0x47)
) ; }

 

Тогда увеличение времени на тех же 100 тактах  по сравнению с предыдущими Test uDSC  269.75  uS делим на 100 и получаем чистое время на DA = DA + (DX*DY) . Вывод результата из DA в время операции вносить не стоит. Назначение строк 58-59 (или 3-4 в этом сообщении) я не понял, может и их надо повторять?

ПС. посмотрел строк 58-59 вобще один раз нужы. Включают DCS просто.

Logik
Offline
Зарегистрирован: 05.08.2014

Чего пишут то! "При использовании команды LD / ST для доступа к SRAM от 0x2100 до 0x28FF, ядро автоматически включает 16-разрядную функцию LD / ST, чтобы включить прямой доступ между SRAM и uDSC." Получается вместо out можна LD / ST но с адресов 0x2100 до 0x28FF куда дублировано обычное ОЗУ.

А еще там сдвиги есть на N бит! Причем хочеш со знаком, хочеш без. И деление быстрое.

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

Logik,  500 циклов

Test uDSC  1344.75  uS
Test Normal  2251.00  uS
Т.е соотношение не меняется . Добавлять повторы в функцию особого смысла не, т.к.  уже её потактово просчитал. 2 такта уйдёт что б внести операнды в адресные регистры. Потом 7 команд по такту описанных в функции, и  1 такт выход из функции. Выходит полный цикл 10 тактов, похоже большая часть времени уходит непонятно на что..:-\   Что-бы повторить вычисление без изменения входных данных достаточно всёго двух тактов -загрузить код операции в временный регистр, и выгрузить его в порт (или одного, если код уже лежит в регистре). На данной операции конечно скорость будет сверхзвуковая )

PS: строки 58-59 просто включают ускоритель. Да! в принципе  можно убрать, включив его один раз в сетапе. Этот регистр 8-битный, и можно им управлять из Си.  Выходит любую операцию функция будет выполнять за 8 тактов. Найти бы этому полезное применение..

Logik
Offline
Зарегистрирован: 05.08.2014

//соотношение не меняется .

И не поменяется, не в нем дело. В эти времена входит много чего - переходы циклов, вызовы функций, извлечение из аккумулятора. Все это вобщем не связано с самим временем DA = DA + (DX*DY). Чтоб исключить эту чепуху надо сделать допустим 500 (или сколько угодно вобщем, но достаточно много) раз с однократным DA = DA + (DX*DY), а потом столькоже с двукратным и вычесть одно из другого чтоб чепуха, которая одинакова в обоих опытах сократилась. Так с точностю до такта можна определить. 

//Потом 7 команд по такту описанных в функции, и  1 такт выход из функции. 

Не факт что эти команды именно при работе с DCS остаются с такими же тактами а не ждут пока насчитают

Хотя и из Ваших цифр уже интересно получается. По первому опыту 269,75/100=2,7мксек По второму 1344,75/500=2,7мксек По разностям, здесь плохо что итератор в первом опыте байт а в втором 2 байта, но (1344,75-269,75)/(500-400)=2,7мксек. Вобщем везде одинаково. Вывод - время самой операции DA = DA + (DX*DY) существенно больше чем на организацию циклов и прочую чепуху и порядка 2,7мксек. Если нужно точней - методику я описал.

//похоже большая часть времени уходит непонятно на что..:-\

Ага, порядка 2,7мксек какраз на работу DCS по расчету математики. Ну немного меньше понятно, но не на много, на те самые тактов 10.

//На данной операции конечно скорость будет сверхзвуковая )

Все проверять нужно, это же китайцы! )))))

Logik
Offline
Зарегистрирован: 05.08.2014

Я вот чего подумал. Включение ускорителя может вызывать его инициализацию на сколькото тактов. И будет влиять сильно, т.к. все тормознется до завершения инита. Возможно.  Надо стр 58-59 в сетап нафиг убирать. 

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

Logik пишет:

Не факт что эти команды именно при работе с DCS остаются с такими же тактами а не ждут пока насчитают

Решил проверить, ниже скетч, выполняет измерение один раз, и только времени работы функции uDSC. Поместил включение таймера прямо перед вызовом ассемблерной вставки , а выключение таймера сразу после.

//Тестирование скорости операции DA= DX*DY  через uDSC
#define tcnt2 (*(volatile uint16_t*)0xB1)
#define tcnt3 (*(volatile uint16_t*)0x94)
#include "lgtx8p.h"
volatile uint32_t data; //для результата ариф. операций
void setup(){
Serial.begin(115200);
Serial.println ("Start..");
TCCR2A=0;TCCR2B=1<<CS20; //запустить таймер
TCCR3A=0;TCCR3B=1<<CS30; //запустить таймер
TCKSR=0; TIMSK1=0; TCCR1A=0; TCCR1B=0; //обнулить лишнее
OCR1A=65535u; OCR1B=65535u;// чтоб удобнее читать регистр флагов
}

void loop(){
cli();
TCNT1=0; TIFR1=TIFR1;
uint16_t dx = tcnt2;
uint16_t dy = tcnt3;
data  = uDSC(dx,dy); 
sei();
Serial.print("Test uDSC  ");
if (TIFR1) {Serial.println("Timer overload");} 
else Serial.print(TCNT1); Serial.println("  tic mk "); 
Serial.print("dx="); Serial.print(dx);
Serial.print(" dy="); Serial.print(dy);
Serial.print(  "dx x dy ="); Serial.println (data); 
Serial.println("..");  
Serial.println("..");  
delay(5000);  
  
  }


volatile uint32_t uDSC(uint16_t dx, uint16_t dy){
TCCR1B=1; //пошёл счёт времени!
asm volatile(  
"ldi r18, 0x80;"     "\n\t" // byte  for DSUEN
"out 0x00, r18;"     "\n\t" // DCSR= 1<<DSUEN
"out 0x10, %[dsdx];" "\n\t" // DSDX = dx 
"out 0x11, %[dsdy];" "\n\t" // DSDY = dy 
"out 0x01, %[opc];"  "\n\t" // DSIR= operation code
"in r22, 0x38;"      "\n\t" // DSAL return 
"in r24, 0x39;"      "\n\t" // DSAH return
: 
: [dsdx] "r" (dx), [dsdy] "r" (dy), [opc] "r" (0x44)
:"r18"
) ; 
TCCR1B=0; //стоп таймер 
}

И получаю:

Test uDSC  10  tic mk
dx=22017 dy=33589dx x dy =739529013

 

Решил ещё один тест провести, вписал включение таймера в начало ассемблерного кода, выключение в конец.

asm volatile(  
"ldi r19,0x01;"       "\n\t" 
"sts 0x81,r19;"       "\n\t" // TCCR1B=1<<CS10
"ldi r18, 0x80;"     "\n\t" // byte  for DSUEN
"out 0x00, r18;"     "\n\t" // DCSR= 1<<DSUEN
"out 0x10, %[dsdx];" "\n\t" // DSDX = dx 
"out 0x11, %[dsdy];" "\n\t" // DSDY = dy 
"out 0x01, %[opc];"  "\n\t" // DSIR= operation code
"in r22, 0x38;"      "\n\t" // DSAL return 
"in r24, 0x39;"      "\n\t" // DSAH return
"sts 0x81,__zero_reg__;"  "\n\t" // TCCR1B=0
: "=r" (data)
: [dsdx] "r" (dx), [dsdy] "r" (dy), [opc] "r" (0x44)
) ; 

Start..
Test uDSC  9  tic mk
dx=18689 dy=40 dx x dy =12648448
 

Добавлено: переписал результаты этих тестов в этом посте, т.к. сам допустил небольшую ошибочку. В общем все накрутки идут когда программа уже выходит из функции.

Logik
Offline
Зарегистрирован: 05.08.2014

//dx=18689 dy=40 dx x dy =12648448

вощето 18689*40=747560. Заметил что уВас множитель заканчивается на 0 а результат - нет. ))

А зачем перешли с операции DA = DA + (DX*DY), код 0х47 на DA = DX*DY, код 0х44? Они могут различатся длительностю.

Не морочтесь с этими таймерами. Когда вносится в код много изменений всегда ошибки влезут. Возмите код из #28 второй Ваш скетч, убедитесь что выдаст как ранее Test uDSC  269.75  uS, это для самопроверки, поменяйте функцию на приведеную в #29 и все, новое время все сразу покажет, т.к. в код добавлена только одна операция, то и время добавится только на неё (с учетом разумеется повтора 100 раз).

 

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

Logik, ну проверил:

Start..
Test uDSC  288.50  uS
Test Normal  451.00  uS

uDSC вырос на 18,75 мкС, тобишь на 0,1875мкС на один круг круг, что равняется 3м тактам, что точно соответствует 3-м добавленным командам. :) Стало быть ещё раз подтвердилось, что функция работает быстро, получается что основной вычислительный ресурс уходит  куда-то ещё.  60мкС на 100 кругов функции , а оставшиеся  200мкС  на подтягивание  в функцию двух 16-битных данных? Очень не правдоподобно :-/

while(n--) {
data  = uDSC(tcnt2,tcnt3);
}