SAM3X8E (Arduino DUE) manipolazione registri PIO

Emicrania con l’aura, vedo tutto seghettato, quindi ti leggero meglio appena passa.

cosa intendi? l’ARM Cortex in generale è superato? obsoleto?

No, non è superato per niente, dicevo che considerare superata la Arduino DUE e non la Zero visto che montano entrambe microcontroller ARM e almeno opinabile.

Per di più la DUE ha un clock è una dotazione interna all’ARM superiore al cortex-0 montato sulla Zero e non escludo che studiando il datasheet del SAM e del cortex molte cose sono simili se non identiche.
Per di più rimanendo in casa Atmel non dobbiamo scontrarci con documentazione di altri produttori che se alla lunga può anche essere giudicata migliore e sempre qualcosa di estraneo a noi abituati alla doc Atmel.

Diciamo che è raro che qualcuno voglia leggere un OUTPUT quando è il programmatore stesso che lo attiva o disattiva, normalmente è importante da parte del programma conoscere lo stato degli INPUT, però su richiesta dovrei riuscire a leggerlo

Per me è un impedimento, in quanto uso il registro per ricavare lo stato di una uscita. Pensa alle uscite temporizzate e/o in pending temporizzato o comunque legate a più di una variabile di stato, queste si accenderanno e spegneranno senza che il programmatore ne possa avere certezza dello stato, per cui o lo salva in una variabile (occupa spazio ram) o con if (pinState(GPIOA, PA7)) legge direttamente lo stato del pin risparmiando ram e leggendo direttamente lo stato e non una copia che potrebbe non essere in sincro.

Ciao.

Niente, ormai sono 10gg che studio i registri, librerie, datasheet e ho capito molte cose, ma non riesco a impostare un pin in INPUT usando i comandi dei PIO … è veramente devastante, non sono rimasto al sam3x8e della DUE, ho letto praticamente tutti i post sulle varie ARM Cortex trovati su google, spulciato i percorsi delle lib del core arduino, le librerie c che atmel mette a disposizione
http://asf.atmel.com/docs/3.4.1/sam.utils.cmsis.cm3_cmsis_example.sam3x_ek/html/globals_func_0x70.html

riesco a leggere tutti i registri, ad abilitare gli OUTPUT, a comadarli se necessario, gestire gli interrupt, visualizzare gli stati, enable dei pio, ma non riesco a fare un set INPUT di un solo pin.

L’unica funzione che imposta il pin in INPUT è il classico pinMode(8,INPUT); che mi attiva in IN tutto il PIO, se vado ad attivare almeno 1 Input su ciascun pio a/b/c/d mi si accendono tutti tranne quelli impostati OUT

mi sono fatto un programma http websocket per vedere in tempo reale il comportamento dei registri con latenza di pochi ms
nell’immagine sotto, la sezione PIO_PDSR era tutta spenta, mi è bastato mettere pinMode(8,INPUT); che tutti sono andati in hight (l’8 appartiene al PIOC) e come si può notare dall’ PIO_PSR solo l’8 si è attivato in enable, quindi solo lui risponderà a variazioni di input, gli altri no. (ma restano a 1 e io non li voglio a 1, anche un digitalread mi restituisce 1 senza averli citati)
Nel PIO_OSR ci sono solo i pin impostati come OUTPUT quindi nessun pin input andrà a scrivere sul quel registro
Nel PIO_PSR ci sono tutti i pin abilitati all’uso sia IN che OUT
Nel PIO_ISR ci sono gli interrupt essi forniscono un breve high quando quel pin cambia stato che esso sia IN oppure OUT, che vada in H o in L

eppure da quello che ho trovato sulle istruzioni atmel

pio_disable_interrupt(p_pio, ul_mask);
    pio_pull_up(p_pio, ul_mask, ul_attribute & PIO_PULLUP);
/* Configure pin as input */
    p_pio->PIO_ODR = ul_mask;
    p_pio->PIO_PER = ul_mask;

sulla libreria del core per vedere cosa fa pinMode(8,INPUT);
wiring_digital.c

extern void pinMode( uint32_t ulPin, uint32_t ulMode )
...
...
case INPUT:
            /* Enable peripheral for clocking input */
           pmc_enable_periph_clk( g_APinDescription[ulPin].ulPeripheralId);
            //Serial.println(" ");
           PIO_Configure(g_APinDescription[ulPin].pPort, PIO_INPUT, g_APinDescription[ulPin].ulPin, 0);
        break ;

        case INPUT_PULLUP:
            /* Enable peripheral for clocking input */
            pmc_enable_periph_clk( g_APinDescription[ulPin].ulPeripheralId );
          PIO_Configure(g_APinDescription[ulPin].pPort, PIO_INPUT, g_APinDescription[ulPin].ulPin, PIO_PULLUP);
        break ;

non ne vuole sapere e non so cosa non ho capito :frowning:

Dirò una stupidaggine, ma visto che deve uscire la Zero e monta un CORTEX, non conviene attendere l'uscita del nuovo IDE e librerie per quella scheda? Magari sarà "compatibile" con la Due ?

ehhhh mi sa che ci toccherà aspettare. Però non è un difetto del SAM .... sono io che non ci arrivo :) :)

@nid: "Cortex" è anche il core del SAM. Per l'esattezza un core ARM Cortex M3

@pablos: le pull-up sono attive di default dopo un reset:

e. After reset, all of the pull-ups are enabled

Quindi se non disattivi le pull-up, le trovi attive su tutti i pin. Era questo quello che intendevi?

Scusa ma pull-up non significa attivare un R interna tra pin e +3,3? Quindi anche in questo caso resterebbe a 1 .... al restart È tutto off quando attivo un solo pin input vanno tutti a on solo pio di quel pin

Non torna, però. Il datasheet è chiaro, dice espressamente che dopo un reset è tutto up. Mi hai messo curiosità, stasera provo con le mie DUE, ne ho... due di Due :stuck_out_tongue_closed_eyes: :stuck_out_tongue_closed_eyes:

Dove trovo lo sketch che hai usato per il test?

ok grazie Leo, ma un attimo però, allora, tutto up che cosa ? il registro PIO-PSR è tutto active al reset si è vero lo ammetto (anche se io li ho disabilitati tutti), ma ciò non toglie che devo attivare almeno un pin in INPUT per ciascu PIO per poterli visualizzare tutti

con queste 4 righe pinMode(8,INPUT); //ne prendo 1 a caso sul PIOC pinMode(17,INPUT); //ne prendo 1 a caso sul PIOA pinMode(20,INPUT); //ne prendo 1 a caso sul PIOB pinMode(14,INPUT); //ne prendo 1 a caso sul PIOD abilito tutte le visualizzazioni sul PDSR vedo anche i pin in output cambiare di stato, tutti e 4 i banchi mi vanno in HIGH e diventano INPUT tranne quelli che sono stati precedentemente dichiarati OUT, è questo che non mi piace, ho bisogno di una visuale completa di ciò che è effettivamente è settato e di ciò che effettivamente è collegato ai pin.

quindi cosa ho fatto li ho disabilitati tutti con PDR = pio disable register PIOA->PIO_PDR = 0xFFFFFFFF; PIOB->PIO_PDR = 0xFFFFFFFF; PIOC->PIO_PDR = 0xFFFFFFFF; PIOD->PIO_PDR = 0xFFFFFFFF; così vedo quali effettivamente sono stati dichiarati nello sketch, che siano IN o OUT non importa, vedo solo quelli actived ma quando vado a settare un solo INPUT qualsiasi tutto il pio PDSR mi va hight.

La mia domanda era come faccio a settare un solo pin in INPUT senza coinvolgere tutto il banco?

Nel chip SAM c'è un sistema di protezione per evitare che si scriva in un registro per sbaglio. Per poter scrivere bisogna in genere attivare un determinato pin, vedo nel caso di PIO che devi attivare il bit WPEN impostando il bit a 0 nel registro PIO_WPMR del corrispondente PIO. Per far ciò devi scrivere contemporaneamente la password nel registro.

Fatto questo, mi pare di capire che devi abilitare il pin ad essere gestito dal PIO, disattivando quindi il multiplexing con altre periferiche. Poi devi disabilitare il pin come output e conseguentemente (credo) il pin si trasforma in input.

Ho paura che sia l'opposto di quel che hai fatto tu con PIOA->PIO_PDR =$FFFFFFFF ....

cavolo non trovo un cavetto per far eun test.. ora lo cerco

Certo che non trovi un cavetto, di sicuro usi qualla baracca di I-Phone !!! ahahahahhaha

pablos:
Certo che non trovi un cavetto, di sicuro usi qualla baracca di I-Phone !!! ahahahahhaha

Avevo un cavetto micro-Usb qui al computer, ma mi è sparito… non vorrei che i figlioli ci abbiano giocato… sono andato a trovarne uno con cui ci ricarico il tablet… :sweat_smile:

La mia domanda era come faccio a settare un solo pin in INPUT senza coinvolgere tutto il banco?

Al momento non riesco a risponderti.
Seguendo la mia idea non sono giunto a niente, ma forse sbaglio qualcosa io perché i registri del SAM non sono come quelli dell’Atmega328 ed è czzto manipolarli.
Inoltre la documentazione di Atmel fa veramente pena, danno informazioni stringatissime. Non si capisce niente.

Inoltre la documentazione di Atmel fa veramente pena, danno informazioni stringatissime. Non si capisce niente.

sono daccordo, va bene Leo tranquillo ci studio ancora se scopro qualcosa di nuovo lo scrivo ... grazie per ora :)

ciao

Questo treadh è più una raccolta di “eventi incongruenti” piuttosto che “ecco come si fa”, mi dispiace, ma lascio traccia di quello che rilevo al momento che non mi convince e mi lascia perplesso, chissà magari tra un anno ripasso e dico quanto ero gnurant.
Non vi sto chiedendo nulla :slight_smile:

Come da immagine postata prima (che sono valori controllati 1000 volte)
I pin abilitati ad essere usati sono 5, sono quelli impostati da me nello sketch, per esattezza sono 4-10-13-15-8:

PIOB->PIO_PER=(1<<27); //Enable PIO for GPIO P13
PIOD->PIO_PER=(1<<5);  //Enable PIO for GPIO P15  

PIOB->PIO_OER=(1<<27); //Enable port pin for output P13
PIOD->PIO_OER=(1<<5);  //Enable port pin for output P15

PIOC->PIO_PER=(1<<29); //Enable PIO for GPIO P10
PIOC->PIO_PER=(1<<26); //Enable PIO for GPIO P4

pinMode(8,INPUT); // in qulche modo il core provvede a farlo diventare Enable PIO for GPIO P8

Questi pin abilitati IN/OUT li possiamo leggere sul registro PIO-PSR e fin qui tutto OK

i comandi sui pin li faccio così con 2 Blink without Delay per osservarne i cambiamenti sui registri e testare velocità di trasmissione oltre che a verificare se uso correttamente gli interrupt (interval =100ms)

if( millis() - previousMillis1 >= interval) {
    previousMillis1 = millis(); 
    
    if (bitRead(PIOB->PIO_ODSR,27) == 0)
    PIOB->PIO_SODR=(1<<27);//Write High Logic on PIOA.13 pin
    else 
    PIOB->PIO_CODR=(1<<27);//Write Low Logic on PIOA.13 pin
   } 

  if( millis() - previousMillis2 >= interval*3) {
    previousMillis2 = millis(); 
    
    if (bitRead(PIOD->PIO_ODSR,5) == 0)
    PIOD->PIO_SODR=(1<<5);//Write High Logic on PIOA.15 pin
    else 
    PIOD->PIO_CODR=(1<<5);//Write Low Logic on PIOA.15 pin
   }

anche qui nessun probema tutto viene eseguito come mi aspettavo tutto lampeggia a dovere a parte l’INPUT 8 che attiva tutto il banco in INPUT inoltre usando nel codice Blink without Delay

 if (digitalRead(13) == 0)

al posto di

 if (bitRead(PIOD->PIO_ODSR,5) == 0)

non funziona niente, ma tralasciamo!

ora il dubbio…
Ho passato 3 anni su questo forum a dire che lo shield ethernet e la SD hanno i pin CS 10 e 4 che vanno impostati in OUTPUT con LOW active interface sugli AVR e come specifica il datasheet dell’atmel il PIO-OSR mi dice 1=Pin Output 0=Pin Input … perchè diavolo non sono presenti il 4 e il 10? ma come ??? lo shield lavora con attivazione su livelli LOW output e sul sam no? :fearful:
se andiamo a mettere questo

pinMode(10,OUTPUT);
pinMode(4,OUTPUT);

oppure questo

PIOC->PIO_OER=(1<<26); //Enable port pin for output P4
PIOC->PIO_OER=(1<<29);  //Enable port pin for output P10

arduino non parte nemmeno :fearful: :fearful: e lo shield è sempre quello che usavo sulla mega,
Forse un giorno capirò il mistero

le impostazioni sui CS il sam le vuole così

SPI.begin(10);
SPI.begin(4);

volendo è possibile cambiare la frquenza di lavoro con l’SPI

//SPI.setClockDivider(10, 2); //Frequenza SPI 42MHz (84/2=42) 
//SPI.setClockDivider(10, 4); //Frequenza SPI 21MHz (84/4=21) 
//SPI.setClockDivider(10, 21); //Frequenza SPI 4MHz  (84/21=4)// default della libreria

http://arduino.cc/en/Reference/DueExtendedSPI

saluti

Seguo ma non posso intervenire, mi manca il tempo di studiare e sperimentare. Qualche giorno addietro in un momento di "svago" ho spulciato sotto asf (atmel), ma la mancanza di tempo non mi ha permesso di isolare il codice e farlo mio, in più non è semplice seguire asf internamente in quanto basta guardare nella cartella sbagliata dove trovi lo stesso nome di file ma per microcontroller differente da quello che stavi seguendo, questa è la conseguenza delle librerie che uniformano le API.

Aiuto morale e stimolo: Vai vai pablos che sei partito bene, dai che vedo il titolo ARM demystification nella sezione Megatopics. :P

Ciao.

Ma gli stessi problemi potremmo averli anche con la Arduino ZERO?
Ovvero una gestione un po’ più complessa dei pin tramite registri?

Bella domanda. Bisognerà vedere come l'IDE gestirà l'accesso alle linee di I/O e come il chip lo farà fare. Ah, io non ho ancora dato un'occhiata al datasheet del microcontrollore utilizzato.

--> http://www.atmel.com/Images/Atmel-42181-SAM-D21_Datasheet.pdf

Dopo le 1470 pagine del SAm3X, le 970 di questo chip mi sembreranno una passeggiata :sweat_smile: :sweat_smile:

PaoloP:
http://www.atmel.com/Images/Atmel-42181-SAM-D21_Datasheet.pdf

Solo per la cronaca, la Zero è ATSAMD21G18, 48pins quindi in quel PDF la D21G (parla di 3 chip)
Mi pare abbastanza diverso questo (Cortex-M0) da quello della Due (Cortex-M3). :fearful:

Si. Credo l'abbiamo fatto perché le sottofamiglie si differenziano per poco tra di loro. Comunque è una versione preliminare del datasheet.