Programmazione Arduino in C puro

ho giusto giusto fattol'altro girno un blick in C puro compilato in avr-gcc... 0 byte di ram

lesto:
ho giusto giusto fatto l'altro girno un blick in C puro compilato in avr-gcc... 0 byte di ram

GRANDE !!!

Guglielmo

Interessante... Riesci a postare qualcosa? Mi intriga l'uso di arduino in c "puro"

attiny85 puro C, blink con ram a 0 byte(testato e funzionante): GitHub - MauroMombelli/attiny85: pure C with attiny85

(edit: osti,mi sa che li ho settati come INPUT, non come OUTPUT! eccoperchè il led era così fioco....)

32u4 puro C, piccolo sketch per testare due cose e da cui vorrei far partire un esperimento di "arduino senza ++" :grin: (testata solo la compilazione e non l'upload/funzionamento), GitHub - MauroMombelli/TestAvr: a easy test to see performace of Arduino vs plain avr

Quindi per usare le "librerie" basta fare la define voluta e si può utilizzare anche l'ide?

ma parli delle eeeprom (in tal caso sì) o del mio codice? in tal caso è tutto fatto SENZA ide (tranne l'upload, che sfrutta l'arduino as ISP, ma il prossimo passo è renderlo autonomo)

Ho capito che ho fatto "confusione"... :-[

gpb01:
Ecco, appunto, una altra cosa DA EVITARE come la peste ... :smiling_imp:
... USATE la AVR libc invece di queste inutili e dispendiose classi C++ !!!
Guglielmo

nel codice di questa nuova libreria ci sono anche i template, non so quanto uso se ne faccia nel core arduinico o se e' la prima volta che vengono usati, ed ho chiesto come occupazione di ram, flash, velocita' di esecuizione come stessero le cose.
L'autore, o almeno credo che fosse lui, dice che ha lo stesso footprint della precedente, pari velocita', ecc. possibile ?
La precedente alla fine non esisteva perche in realta' sono giusto due richiami della avrlibc, possibile che andando verso programmazione spinta c++ e template si occupino le stesse risorse ?

guarda che (quasi) tutte le librerie arduino sono classi, dalla EEPROM alla Serial e in generale (quasi)tutto quello che è in formato xxx.yyy() è un a classe (salvo define o altre magie)

i template sono molto potenti mafunzionano in fase di COMPILAZIONE; quindi non mi stupirei se il peso della libreria varia notevolmente in base alle funzionalità usate, ma prorpio in base aqeusta loro potenza spesso vengono ABUSATI fino a creare codice illeggibile o inmantenibile.

linus torvald scrisse:

C++ is a horrible language. It's made more horrible by the fact that a lot
of substandard programmers use it, to the point where it's much much
easier to generate total and utter crap with it. Quite frankly, even if
the choice of C were to do nothing but keep the C++ programmers out,
that in itself would be a huge reason to use C.
[...]
In other words, the only way to do good, efficient, and system-level and
portable C++ ends up to limit yourself to all the things that are
basically available in C. And limiting your project to C means that people
don't screw that up, and also means that you get a lot of programmers that
do actually understand low-level issues and don't screw things up with any
idiotic "object model" crap.

completo: http://article.gmane.org/gmane.comp.version-control.git/57918

Grande :slight_smile:
Riscrivere l'intero core arduino in C è fattibile ?

Grande :slight_smile:
Riscrivere l'intero core arduino in C è fattibile ?

Si, ma alla fine lo useranno in pochi, e quei pochi si stancheranno presto.
Io quella lib l'ho guardata per 30 secondi e non mi ha fatto una cattiva impressione.
Sicuramente astrae tanto e l'astrazione sembra buona, certo in certi contesti si potrebbe volere una maggiore efficienza e al costo di quasi zero astrazione si possono usare le funzioni delle avrlibc.

Linus noi sappiamo quanto drastico sia nelle sue scelte e sembra che non consideri programmatori quelli che usano il C++. In quello che dice c'è della verità ma non è l'unica.
Il C++ non è il male assoluto come alcuni professano e non lo è anche in embedded con risorse limitate. Arduino in C non avrebbe il seguito che ha avuto per cui in quest'ottica non si può considerare il C++ il male assoluto.

In C le classi non esistono ma la programmazione orientata agli oggetti è realizzabile, ore se farcisci di automatismi comodi gli oggetti C ti ritrovi con lo stesso problema che si presenta in C++, ma hai perso le classi i metodi e tutto quello che di buono c'è nel C++.

Per usare il C con profitto devi essere un programmatore sgamato e anche li i bug sono dietro l'angolo, con il C++ puoi essere ingenuo e scrivere codice senza bug, sempre che le librerie siano scritte con questo obbiettivo. Es. vedi vector, string e gli iteratori C++ non presenti nel C++ di arduino perché troppo onerosi per le limitate risorse disponibili.

Io entrambe i linguaggi li digerisco abbastanza bene, ma ho delle difficoltà con, l'ereditarietà, l'astrazione, ecc che però sono concetti da studiare a prescindere dal C++ e che si possono applicare con ogni linguaggio orientato agli oggetti, evidentemente non sono molto portato verso l'astrazione.

Ciao.

@mod: potete splittare la discussione in "core puro c" o simile?

con il C++ puoi essere ingenuo e scrivere codice senza bug

è proprio questa falsa assuzione a portare il buon linus a fare queste dichiarazioni, se leggi lui ce l'ha con quelli che sono poco "sgamati", perchè PRETENDE che il codice prodotto sia di altissima qualità, e i risultati sono sotto gli occhi di tutti. Che poi sia giusto o sbagliato, è un modello che funziona e su grandissima scala.

MA BANDO ALLE CIANCE (guerre di religione)

vorrei far notare come la Serial, per esempio, invece che essere una classe potrebbe essere tranquillissimamente una struct, per esempio

lesto:
MA BANDO ALLE CIANCE (guerre di religione)

... esatto, ed è il motivo fondamentale per cui mi astengo da queste discussioni :wink:

Guglielmo

L'altro giorno mi sono trovato a parlare di buon senso, qualcuno mi disse; sai che c'è gente che non sa cosa vuol dire? Prova tu a descrivere come si arriva ad agire con buon senso.

Ne è venuta fuori una risposta singolare.

La risposta, singolare e soggettiva:
Il buon senso ti porta ad agire nel verso in cui arrechi il minor danno. Se tenti di fare 100 passi in avanti ti potresti ritrovare ad averne fatto 100 indietro, per cui il rischio è troppo alto, quindi limita il danno ad un passo e male che vada hai perso un passo.

MA BANDO ALLE CIANCE (guerre di religione)

Argomentare sul C/C++ non mi sembra possa avere risvolti dannosi. Includere nella discussione chi non considera altre religioni può portare ad una perdita di tempo (danno relativo).

Con il C++ ci ho scritto più di una applicazione e a differenza del C il codice si capisce subito cosa fa, vogliamo considerare questo un pregio del C++?.

Il processore ARM velocizza le ISR rendendo superfluo il prologo e l'epilogo asm, cosa che in AVR possiamo scegliere di gestire manualmente, ma quanti hanno voglia di scendere così in basso? Io no ci ho voglia, ma se dovesse essere necessario mi tocca metterci mano.

digitalWrite è lenta perché viene compilata dal C++? No, è l'implementazione che è lenta, il collo di bottiglia è la lettura dalla flash sia che scrivi in C/C++/asm.

vorrei far notare come la Serial, per esempio, invece che essere una classe potrebbe essere tranquillissimamente una struct, per esempio

Si, ma scordati il polimorfismo di print. Non ci vuoi rinunciare, si può fare anche in C ma pensi che in C sia più rapido che in C++? no no, siamo li.

typedef volatile uint8_t 	reg8b_t;

struct __port_t
{
    reg8b_t r_pin;
    reg8b_t r_ddr;
    reg8b_t r_pout;

};

typedef struct __port_t port_t;

#define GPIOA ((port_t *) &_SFR_IO8(0x00))
#define GPIOB ((port_t *) &_SFR_IO8(0x03))
#define GPIOC ((port_t *) &_SFR_IO8(0x06))
#define GPIOD ((port_t *) &_SFR_IO8(0x09))


// define for atmega164, 324 or 644
//      Name        PORTx,      Bit
#define GPIO_A0     GPIOA,      0

// Definizione del tipo di argomento GPIO
#define GPIO_T port_t *port, uint8_t bit

inline void gpio_on(GPIO_T)
{
    port->r_pout |= _BV(bit);       // imposta il bit on
}

Il codice sopra è quanto di meglio sono riuscito a fare. L'usabilità è buona, l'efficienza è identica alla manipolazione delle porte.

Comparata a digitalWrite manca di flessibilità, cioè digitalWrite(8 + offset, HIGH), con gpio_on() non lo posso fare. Lo stack lavora sempre con 2 parametri.

In C mi devo inventare qualcosa per fare 8 + offset.

Tirando le somme.
Manipolare le porte direttamente offre:

  • Flessibilità massima
  • Efficienza massima
  • Usabilità scarsa
  • Leggibilità scarsa

Ciao.

Argomentare sul C/C++ non mi sembra possa avere risvolti dannosi. Includere nella discussione chi non considera altre religioni può portare ad una perdita di tempo (danno relativo).

devo ammettere che non oso scendere troppo nella discussione perchè MI MANCANO LE CONOSCENZE per esprimere un vero giudizio obiettivo; non conoscendo i template che alla fin fine sono la vera differenza del c++ (tutto il resto, polimorfismo compreso, lo puoi fare in C.. guarda il "c con oggetti", è il sistema con cui è starto scritto Quake 2 per esempio, Phil's guide to object-oriented ANSI C ed esistono vari standard e framework per farlo)

digitalWrite è lenta perché viene compilata dal C++? No, è l'implementazione che è lenta, il collo di bottiglia è la lettura dalla flash sia che scrivi in C/C++/asm.

vero che non è c++, vero che è lenta ma per tutti i check che fa (e il conseguente spreco di ram), vero anche che si può scrivere molto più veloce con qualche piccolo accorgimento. (vedi fastDigitalWrite).

Comparata a digitalWrite manca di flessibilità, cioè digitalWrite(8 + offset, HIGH), con gpio_on() non lo posso fare. Lo stack lavora sempre con 2 parametri.

allora, quì nasce un grandissimo problema che è la numerazione deipin di mamma atmel che è da pazzi (come mi ha fatto notare il buon leo), specialmente se confronti tiny, mega e 32u4.

In realtà sto creando un sistema di x-macro che in base alla presenza o meno di un registro genera una union/struct bitfield che permette la manipolazione diretta del bit come se fosse una variabile. BONUS: se proverai a fare pin16 = HIGH; (e non hai ilpin16 sulla board) ti darà errore di compilazione :stuck_out_tongue: (sto diventando sempre di più un FANATICO degli errori a compile time)

l'idea che sto ragionando per rendere "sane" le numerazioni è di dire che i portA sono i primi 8, etc, però ad esempio sui tiny85 mi ritrovo ad avere solo portB, quindi da pin9 a pin17
In compenso i pin si autodichiarano in base alla architettura di compilazione e NON necessitano di header ad-hoc per la numerazione

quindi per l'esempio del PIN16, sai che corrisponde a 16/8 = 2 => PORTC (A=0, B=1, C=2,...), e 16%8 = 0 => primo bit (LSB)

il vantaggio è che tali strutture/enum essendo costanti (son PUNTATORI ai registri) sono in flash e occupano solo 8bit cadauna. però ci sto ancora lavorando, magari oggi finisco di sistemare le mie idee e butto giù qualcosa posto (sperando che nel frattempo qualche mod divida la discussione)

lesto:
@mod: potete splittare la discussione in "core puro c" o simile?

Fatto

leo72:
Fatto

grazie, ora posso iniziare a spammare seriamente sull'argomento

partiamo dalla soluzione base al problema di cui sopra (notare che gli array NON usano ram, ma l'operazione / e % è assai pesante, e non c'è l'#ifdef su ogni elemento dell'array e il famoso check del pin):

volatile uint8_t *set_reg[] PROGMEM = {&DDRA, &DDRB, &DDRC, &DDRD, &DDRE, &DDRF};
volatile uint8_t *out_reg[] PROGMEM = {&PORTA, &PORTB, &PORTC, &PORTD, &PORTE, &PORTF};
volatile uint8_t *in_reg[] PROGMEM = {&PINA, &PINB, &PINC, &PIND, &PINE, &PINF};

void pinMode(uint8_t pin, uint8_t status){
	uint8_t mask = 1 << (pin % 8);
	if (status == OUTPUT){
		*set_reg[pin/8] &= (uint8_t) (~mask);
	}else{
		*set_reg[pin/8] |= (uint8_t) (mask); 
	}
}

void digitalWrite(uint8_t pin, uint8_t status){
	uint8_t mask = 1 << (pin % 8);
	if (status == LOW){
		*out_reg[pin/8] &= (~mask);
	}else{
		*out_reg[pin/8] |= mask; 
	}
}

uint8_t digitalRead(uint8_t pin){
	uint8_t mask = 1 << (pin % 8);
	return *in_reg[pin/8] & mask?HIGH: LOW;
}

Non credo sia molto pesante. La divisione è uno shift, per mod c'è da vedere come viene tradotto in asm.

Vedo PORTF quindi si tratta di una Mega.

Appena posso provo il tuo codice.

Comunque c'è sempre il collo di bottiglia, cioè la lettura dalla flash.

Quando ho cominciato con arduino facevo riferimento ai pin della scheda, poi ho sentito la necessità di scendere al riferimento delle porte del micro, forse ciò è avvenuto in corrispondenza del mio primo standalone. Dal quel momento non mai sentito la necessità di fare riferimento alla dicitura della board e ancora adesso la trovo una complicazione.

Ciao.

Non credo sia molto pesante. La divisione è uno shift, per mod c'è da vedere come viene tradotto in asm.

è uno sfift se è una potenza di 2 il divisiore..
la mod però è la vera pesantezza in persona, certo non come le trigonometriche, ma mi pare vadaa a tentativi.

Vedo PORTF quindi si tratta di una Mega.

no, era un esempio senza #ifdef per essere più leggibile.

ogni registro dovrebbe essere

#ifdef DDRA
&DDRA
#endif

Comunque c'è sempre il collo di bottiglia, cioè la lettura dalla flash.

quindi la soluzione è assicurarsi che ci siano poche istuzioni ma effettive :stuck_out_tongue:

dicitura della board e ancora adesso la trovo una complicazione.

concordo

EDIT: sistemati tag

x iscrizione