Ottimizziamo il codice del core di Arduino

MauroTec: Non è né banale né poco importante e solo che in questa fase non serve sapere cosa sono quelle #define. Non vorrei ci si lanciassi in modifiche pesanti al core per almeno un motivo:

Perfettamente d'accordo. La preoccupazione era solo che quelle define facessero compilare in maniera diversa parte del core e perciò tra i due IDE ci potessero essere parti diverse da modificare.

Le definizioni delle variabili per la compilazione nella 1.5.x sono in platform.txt e board.txt, che a tutti gli effetti fanno parte del core. Ci sono definiti anche PID e VID. Questi due file non possono essere ignorati per capire il funzionamento dell'IDE. (ci ho sbattuto un po' la testa quando ho integrato il core tiny per la 1.5.x)

Esempio per la UNO

uno.name=Arduino Uno

uno.vid.0=0x2341
uno.pid.0=0x0043
uno.vid.1=0x2341
uno.pid.1=0x0001

uno.upload.tool=avrdude
uno.upload.protocol=arduino
uno.upload.maximum_size=32256
uno.upload.maximum_data_size=2048
uno.upload.speed=115200

uno.bootloader.tool=avrdude
uno.bootloader.low_fuses=0xFF
uno.bootloader.high_fuses=0xDE
uno.bootloader.extended_fuses=0x05
uno.bootloader.unlock_bits=0x3F
uno.bootloader.lock_bits=0x0F
uno.bootloader.file=optiboot/optiboot_atmega328.hex

uno.build.mcu=atmega328p
uno.build.f_cpu=16000000L
uno.build.board=AVR_UNO
uno.build.core=arduino
uno.build.variant=standard

Ad esempio se uno volesse potrebbe aggiungere le righe per l'AVR Dragon in programmers.txt e usarlo con l'IDE.

EDIT: In platform.txt ci sono anche i flag per l'USB che rimanda alle variabili definite in board.txt

build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}'

è stato fatto apposta per permettere una facile integrazione di piattaforme esterne, anche custom; questo, unito al fatto di poter compilare e uppare da riga di comando, trasforma arduino da semplice ide a toolchain "appendibile" a valle di un ide custom con board custom; ciò evita il proliferare di arduino IDE cloni, e la conseguente entropia

HardwareSerial è stata scritta molto tempo fà, prima di toccarla bisogna decidere come intervenire.

HardwareSerial dovrebbe essere visto come il driver per accedere all'hardware, la gestione del parity error ecc, dovrebbe essere di competenza del protocollo. Se il protocollo prevede la gestione degli errori allora in caso di errori deciderà molto probabilmente di richiedere nuovamente il dato o il frame a seconda della interfaccia.

Qui occorre qualcuno che si sprema le meningi per organizzare una HardwareSerial che permetta di abilitare o meno la gestione degli errori e chiami delle funzioni utente a seconda dell'errore. A complicare un poco le cose c'è il fatto che HardwareSerial viene "pre-instanziata" e quindi bisogna usare metodi set e get per abilitare la gestione degli errori. Se c'è qualcuno che sa come nel codice reale si deve comportare un protocollo in cui il dispositivo dati rileva un errore, parli ora o taccia per sempre. :P

Perfettamente d'accordo. La preoccupazione era solo che quelle define facessero compilare in maniera diversa parte del core e perciò tra i due IDE ci potessero essere parti diverse da modificare.

Ok, non avevo capito che l'obbiettivo era questo. Comunque quelle -Dxxx si usano spesso e addirittura partono dal file di progetto C++, come es APPLICATION_NAME "chichi", APPLICATION_VENDOR = Mtec, APPLICATION_VERSION ecc e bene che siano visibili in tutte le unit, poi queste possono anche non usarle. Io ne faccio uso per abilitare o neno i messaggi di debug dal file di progetto, come anche avrlibc li usa per abilitare o meno i messaggi di "assert".

Ciao.

io userai una funzione handler che passa l'utente, stile attachInterrupt per intenderci. Non modifica nulla "nel passato", ma aggiunge potenza nel futuro :)

Qualcosa del tipo:

void myErrorHandler(int err);

Serial.setErrorHandler(myErrorHandler)

Dici che può bastare, oppure ci facciamo anche passare il puntatore a Serial? Oppure (const HardwareSerial &serial, int err)

PS: ho aggiornato arduinochanged.zip

Ciao.

ci stavo pensando anche io, si crea una dipendenza ciclica, un pò brutta come cosa, e poi serial è statica...

diciamo che per le classi NON statiche avrei fatto col puntatore, ma in questi casi no. Ovvio che avrai 3 hadler nel caso di 3 seriali.

Penso che se si vogliono gestire gli errori c'è necessità di un comportamento flessibile. Una funzione predefinita potrebbe essere fornita internamente e se si vuole maggiore flessibilità, si può usare Serial.setErrorHandler(). La funzione utente verrebbe fornita solo per l'instanza di HardwareSerial che si ha intenzione di usare. Cioè la HardwareSerial deve essere pensata in modo che lavori di default nel modo attuale o simile, poi se l'utente vuole maggiore flessibilità si fa ricorso al metodo.

Lasciamo decantare la cosa un poco, vediamo se ci sono altri interventi, poi isolo la HardwareSerial creo codice di test e vediamo cosa ne esce fuori.

Ciao.

facciamo il punto, che io sto preparando il repo remoto, la toolchain è pronta.

Devoassolutamente togliere il flag anti-warning, poi?

dobbiamo risolvere il PROGMEM

Il flag anti-warning nella 1.5.x si elimina modificando il file platform.txt Mi pare di averlo già scritto qualche post indietro.

sì, trovato il flag c e c++, grazie

lesto: dobbiamo risolvere il PROGMEM

Dove ??? In Print.cpp era gié stato risolto ... verso l'inizio di questo thread ... comunque :

size_t Print::print(const __FlashStringHelper *ifsh)
{
  PGM_P p =  (PGM_P)ifsh;
  size_t n = 0;
  while (1) {
    unsigned char c = pgm_read_byte(p++);
    if (c == 0) break;
    n += write(c);
  }
  return n;
}

Guglielmo

edit: sto cercando di partire da capo, per fare il punto dove siamo arrivati. Il primo errore in assoluto è:

WString.cpp:189:26: error: ISO C++ forbids declaration of 'type name' with no type [-fpermissive]
  strcpy_P(buffer, (const prog_char *)pstr);
  1. in WString.cpp sostituire le 2 occerrenze di prog_char con char (a verede il core attuale arduino x la nuova toolchain, hanno anche cambiato strcpy_P in strcpy)

  2. In Print.cpp

const char PROGMEM *p = (const char PROGMEM *)ifsh

diventa

const char *p PROGMEM = (const char *)ifsh;

et voilà, compilato senza warning e/o errori!

edit: per il punto 2 la branch di arduino non sembra avere la modifica. Quindi ora sto clonando il loro branch per vedere se sono riusciti a risolvere magari mettendo la define in una ifdef

ok, loro hanno fixato in aplro modo, probabilmente alla diefine di PROGMEM o qualcosa del genere.

I warning ci sono, non avevo attivato -Wall, però sono molto differenti:

versione branch arduino;

/home/mauro/git/ArduinoMod/Arduino/build/linux/work/hardware/arduino/cores/arduino/HardwareSerial.cpp: In function 'void store_char(unsigned char, ring_buffer*)':
/home/mauro/git/ArduinoMod/Arduino/build/linux/work/hardware/arduino/cores/arduino/HardwareSerial.cpp:98: warning: comparison between signed and unsigned integer expressions
/home/mauro/git/ArduinoMod/Arduino/build/linux/work/hardware/arduino/cores/arduino/HardwareSerial.cpp: In function 'void __vector_18()':
/home/mauro/git/ArduinoMod/Arduino/build/linux/work/hardware/arduino/cores/arduino/HardwareSerial.cpp:127: warning: unused variable 'c'
/home/mauro/git/ArduinoMod/Arduino/build/linux/work/hardware/arduino/cores/arduino/HardwareSerial.cpp: In member function 'void HardwareSerial::begin(long unsigned int, byte)':
/home/mauro/git/ArduinoMod/Arduino/build/linux/work/hardware/arduino/cores/arduino/HardwareSerial.cpp:368: warning: unused variable 'current_config'
/home/mauro/git/ArduinoMod/Arduino/build/linux/work/hardware/arduino/cores/arduino/HardwareSerial.cpp: In member function 'virtual size_t HardwareSerial::write(uint8_t)':
/home/mauro/git/ArduinoMod/Arduino/build/linux/work/hardware/arduino/cores/arduino/HardwareSerial.cpp:467: warning: comparison between signed and unsigned integer expressions

/home/mauro/git/ArduinoMod/Arduino/build/linux/work/hardware/arduino/cores/arduino/Tone.cpp:119: warning: only initialized variables can be placed into program memory area

/home/mauro/git/ArduinoMod/Arduino/build/linux/work/hardware/arduino/cores/arduino/Print.cpp: In member function 'size_t Print::print(const __FlashStringHelper*)':
/home/mauro/git/ArduinoMod/Arduino/build/linux/work/hardware/arduino/cores/arduino/Print.cpp:44: warning: '__progmem__' attribute ignored

1.5.5 cvon toolchain e mnodifiche di cuisopra:

In file included from /home/mauro/arduino-1.5.5-MOD toolchain/hardware/arduino/avr/cores/arduino/IPAddress.cpp:3:0:
/home/mauro/arduino-1.5.5-MOD toolchain/hardware/arduino/avr/cores/arduino/IPAddress.h: In member function 'IPAddress::operator uint32_t()':
/home/mauro/arduino-1.5.5-MOD toolchain/hardware/arduino/avr/cores/arduino/IPAddress.h:52:55: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
     operator uint32_t() { return *((uint32_t*)_address); };
                                                       ^
/home/mauro/arduino-1.5.5-MOD toolchain/hardware/arduino/avr/cores/arduino/IPAddress.h: In member function 'bool IPAddress::operator==(const IPAddress&)':
/home/mauro/arduino-1.5.5-MOD toolchain/hardware/arduino/avr/cores/arduino/IPAddress.h:53:75: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
     bool operator==(const IPAddress& addr) { return (*((uint32_t*)_address)) == (*((uint32_t*)addr._address)); };
                                                                           ^
/home/mauro/arduino-1.5.5-MOD toolchain/hardware/arduino/avr/cores/arduino/IPAddress.h:53:108: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
     bool operator==(const IPAddress& addr) { return (*((uint32_t*)_address)) == (*((uint32_t*)addr._address)); };

/home/mauro/arduino-1.5.5-MOD toolchain/hardware/arduino/avr/cores/arduino/HardwareSerial.cpp: In function 'void __vector_18()':
/home/mauro/arduino-1.5.5-MOD toolchain/hardware/arduino/avr/cores/arduino/HardwareSerial.cpp:89:21: warning: unused variable 'c' [-Wunused-variable]
       unsigned char c = UDR0;
                     ^
/home/mauro/arduino-1.5.5-MOD toolchain/hardware/arduino/avr/cores/arduino/HardwareSerial.cpp: In member function 'void HardwareSerial::begin(long unsigned int, byte)':
/home/mauro/arduino-1.5.5-MOD toolchain/hardware/arduino/avr/cores/arduino/HardwareSerial.cpp:329:11: warning: unused variable 'current_config' [-Wunused-variable]
   uint8_t current_config;

Se vai un po' indietro Mauro aveva analizzato il problema di HardwareSerial ... era un po' un casino se ricordo ... ma alla fine aveva proposto una soluzione ... :roll_eyes:

Guglielmo

non è questo ilpunto. NOn capisco perchè la versione 1.5.5 liscia (solo la toolchian modoficata) NON da quell'errore!!

Scusa ... quale errore ? A che riga ?

Perché su HardwareSerial da dei warning più o meno simili, mentre vedo altre cose relative però alla Tone.cpp ed alla Print.cpp ... :roll_eyes:

Guglielmo

Purtroppo sono poco attivo di recente, me ne capita una al giorno, pazienza.

Dunque io ancora non ho funzionante la 1.5.x, ora provo a compilare, se riuscissi poi dovrei anche fare in modo che L'IDE usi la toolchain installata nel sistema. Uso avr-gcc-4.7.2 ufficiale di fedora, che di base è come la 4.3.4 di atmel. C'è da notare che nella doc c'è la builtin di avr-gcc __flashN dove N è un numero, dalla doc mi sembra di capire che usando __flash non è più necessario il supporto avr-libc, cioè non serve più pgm_read_byte() ecc, tuttavia ci sono delle limitazioni che ancora non ho approfondito.

La nuova caratteristica "potrebbe" anche portare grande vantaggio in termini di velocità e spazio occupato, ma questo è ancora da verificare in dettaglio.

@lesto

const char *p PROGMEM = (const char *)ifsh;

Dovrebbe invece diventare

PGM_P p =  (PGM_P)ifsh;

In avr-libc PGM_P è così definita:

#ifndef PGM_P
#define PGM_P const char *
#endif

PROGMEM si espande in un attributo attribute((progmem)) che ha senso usare quando vogliamo che un dato venga posizionato in progrmem. Dichiarare un puntatore const char *p PROGMEM non ha senso, perché manca il dato da posizionare in progmem. Ha senso invece const PROGMEM myString[] ="mystring", nota che il puntatore è in ram e contiene un indirizzo di memoria flash. Quindi PROGMEM è riferito al dato "myString" è non al tipo di variabile.

Stessa cosa per const void * definito in avr-libc così:

#ifndef PGM_VOID_P
#define PGM_VOID_P const void *
#endif

Ripeto, usa PROGMEM quando vuoi che un dato venga salvato in area flash, questo significa che tutte le dichiarazioni in cui compare PROGMEM deve comparire anche il dato da salvare in flash, se non c'è il dato non usare PROGMEM, ma solo PGM_P o PGM_VOID.

Qui sotto, p è un puntatore che vive in RAM e il contenuto di questo indirizzo RAM punta ad un indirizzo in flash, visto che non c'è il dato da spostare in flash PROGMEM è superfluo. Se p lo salvassimo in flash dovremmo avere anche un puntatore in ram che contiene l'indirizzo flasg in cui si trova p.

const char *p PROGMEM = (const char *)ifsh;

Ho capito che questo non è ancora chiaro e ho ribadito il concetto.

Ora provo a compilare la 1.5.x

ciao.

Scusa ... quale errore ? A che riga ?

scusa warinig, non errori.

@MauroTec me lo leggo con più calma

Ok, compilato e avviato con successo L'ide 1.5.x. In pratica è bastato: cd build ant ant run

....e dopo aver macinato qualche minuto è comparsa l'interfaccia dell'IDE arduino, con su caricato uno sketch di default. Compilato con 4.7.2 (di fedora) in effetti dava proprio l'errore, aggirabile con la macro di compatibilità. Quindi dalla 4.7.2 prog_char e compagni sono già deprecati.

Ora vedo nei post precedenti come si abilita -wall.

Ciao.