I've also posted this in I2C topic, the solution is there:

http://beagleboard.org/Community/Forums/?place=msg%2Fbeagleboard%2FDAXyYJOrDIc%2FDZ8WKkRWaC0J


Il giorno lunedì 13 luglio 2015 09:49:20 UTC+2, Gianfranco Rosso ha scritto:
>
> I want to manage the I2C1 module by the PRU, in order to interface some 
> I/O expanders (MCP23017 by Microchip).
> I use may own "cape" without the plug-n' play eeprom (one of the next 
> steps will be adding management for DCAN0 and DCAN1 so i'll need these pins 
> too...).
> So, at present, there are just 2 MCP23017 connected to the P9.17 and P9.18.
>
> I load the *cape-universal* into slots and then I use *configure-pin* 
> command to set P9.17 and P9.18 as *i2c*
>
> I've started from an example into the *am335x_pru_package-master* and 
> wrote my own C PRU loader.
> Very simple, it just:
>
>    - loads the PRU code
>    - init the data exhanged with the PRU
>    - start the PRU
>    - wait for ESC key press
>    - signal to the PRU to stop
>    - wait for the PRU stop
>    - exit.
>
>
> Also the assembly PRU code is simple: 
>
>    - init I2C1 module (by writing registers PSC, SCLL, SCLH, CON)
>    - init 1st I/O expander as 16 inputs (even if at power on it's already 
>    set as input)
>    - init 2nd I/O expander as 16 outputs
>    - cicle reading status of inputs from 1st expander and echoing to the 
>    outputs of 2nd expander
>    - exit cycle and halt when receive stop flag from the loader
>
> for send and receive I2C messages I use register SA, CNT, DATA and CON.
>
>
> That's very simple and linear... pity, it doesn't work.
>
> *I didn't see any activity at all in P9.17 and P9.18*.
>
> The PRU code is surely running, as I add a cycle counter and show it in 
> the loader while it's waiting for ESC keypress, and also the PRU code 
> correctly stops at the loader command.
>
> I was expecting that the PRU code stalls if I2C bus doesn't work, as there 
> are waiting cycles both for STOP condition or for CNT reaching zero 
> (depending on the write or read message sending).
>
> But it seems running, and running very fast also: the cycle counter is 
> incremented to a very fast rate (over 550 kcycles/s)  that's not compatible 
> with the correct executing of I2C sequences (I've setted the module for 
> 400Kbps rate... so the PRU cycle it's even faster than a single I2C bit 
> time!).
>
>
> I'm surely doing something wrong, but I cant fugure what.
>
> Any idea?
>
> Suggestions?
>
>
> Inserisci qui il codice...
> .origin 0
> .entrypoint START
>
> #include "iic_ioexp.hp"
>
> //costanti per l'accesso al modulo I2C1
> #define I2C1_BASE            C2                //base registri I2C1 nella 
> tabella costanti
> #define I2C_SYSC            0x10            //offset del registro I2C_SYSC
> #define I2C_STAT_RAW        0x24            //offset del registro 
> I2C_STATUS_RAW
> #define I2C_SYSS            0x90            //offset del registro I2C_SYSS
> #define I2C_CNT                0x98            //offset del registro 
> I2C_CNT
> #define I2C_DATA            0x9C            //offset del registro I2C_DATA
> #define I2C_CON                0xA4            //offset del registro 
> I2C_CON
> #define I2C_SA                0xAC            //offset del registro I2C_SA
> #define I2C_PSC                0xB0            //offset del registro 
> I2C_PSC
> #define I2C_SCLL            0xB4            //offset del registro I2C_SCLL
> #define I2C_SCLH            0xB8            //offset del registro I2C_SCLH
>
> #define I2C_CMD_ENABLE        0x8400            //modulo I2C abilitato 
> come master
> #define I2C_CMD_TX            0x0200            //modulo I2C in 
> trasmissione
> #define I2C_CMD_RX            0x0000            //modulo I2C in ricezione
> #define I2C_CMD_START        0x0001            //modulo I2C richiesta 
> generazione sequenza START
> #define I2C_CMD_STOP        0x0002            //modulo I2C richiesta 
> generazione sequenza STOP
>
>
> //costanti per l'accesso all'I/O expander MCP23017
> #define IO_EXP0                0x20            //7bit I2C address dell'I/O 
> expander 0 (ingressi)
> #define IO_EXP1                0x21            //7bit I2C address dell'I/O 
> expander 1 (uscite)
>
> #define IO_EXP_IODIRA        0x00            //indirizzo registro IODIRA 
> dell'I/O expander 
> #define IO_EXP_GPIOA        0x12            //indirizzo registro GPIOA 
> dell'I/O expander
>
> //======================================================================
>
> //macro che attende fine sequenza verificando generazione seqeunza di STOP
> .macro I2C_WAIT_BY_STOP
> _CHECK:
>     LBCO r1.w0, I2C1_BASE, I2C_CON, 2
>     QBBS _CHECK, r1.t1
> .endm    
>
> //macro che attende fine sequenza verificando generazione seqeunza di STOP
> .macro I2C_WAIT_BY_COUNT
> _CHECK:
>     LBCO r1.w0, I2C1_BASE, I2C_CNT, 2
>     QBNE _CHECK, r1.w0, 0
> .endm
>
>
> //======================================================================
>
> START:
>     // clear that bit
>     LBCO r0, C4, 4, 4
>     CLR r0, r0, 4
>     SBCO r0, C4, 4, 4
>
>     //------------------------------------------------------------------
>     //configurazione modulo I2C1
>     
>     //reset del modulo I2C1
>     MOV r1.w0, 0x0002    
>     SBCO r1.w0, I2C1_BASE, I2C_SYSC, 2
>     
>     MOV r1.w0, 0x0000    
>     SBCO r1.w0, I2C1_BASE, I2C_SYSC, 2
>
> //    //attesa fine reset modulo
> //_WAIT_RDONE:
> //    LBCO r1, I2C1_BASE, I2C_SYSS, 4
> //    QBBC _WAIT_RDONE, r1.t0    
>     
>     //configura prescaler e durata SCL H/L per avere 400kHz
>     MOV r1.b0, 4                //prescaler=4+1 --> 
> ICLK=SCLK/prescaler=100/5=20MHz (nel reference manual raccomandano circa 
> 24Mhz) 
>     SBCO r1.b0, I2C1_BASE, I2C_PSC, 1
>     
>     MOV r1.b0, 18                //durata SCL L=18+7 --> 
> tLOW=1/ICLK*(SCLL+7)=1/20E6*(18+7)=1.25us
>     SBCO r1.b0, I2C1_BASE, I2C_SCLL, 1
>     
>     MOV r1.b0, 20                //durata SCL H=20+5 --> 
> tHIGH=1/ICLK*(SCLH+5)=1/20E6*(20+5)=1.25us
>     SBCO r1.b0, I2C1_BASE, I2C_SCLH, 1
>
>     //abilita modulo
>     MOV r1.w0, I2C_CMD_ENABLE
>     SBCO r1.w0, I2C1_BASE, I2C_CON, 2
>
>     //------------------------------------------------------------------
>     //inizializzazione IOEXP 0
>     
>     //indirizzo slave
>     MOV r1.w0, IO_EXP0            
>     SBCO r1.w0, I2C1_BASE, I2C_SA, 2
>
>     //n. byte da spedire
>     MOV r1.w0, 3            
>     SBCO r1.w0, I2C1_BASE, I2C_CNT, 2
>
>     //riempie FIFO
>     MOV r1, IO_EXP_IODIRA | 0x00FFFF00        //tutti i pin come ingressi 
> (in realta' e' gia' cosi' dal POR)
>     SBCO r1.b0, I2C1_BASE, I2C_DATA, 1
>     SBCO r1.b1, I2C1_BASE, I2C_DATA, 1
>     SBCO r1.b2, I2C1_BASE, I2C_DATA, 1
>
>     //attesa bus free
> _WAIT_BB:
>     LBCO r1, I2C1_BASE, I2C_STAT_RAW, 4
>     QBBS _WAIT_BB, r1.t12
>
>     //comando scrittura
>     MOV r1.w0, I2C_CMD_ENABLE | I2C_CMD_TX | I2C_CMD_START | I2C_CMD_STOP
>     SBCO r1.w0, I2C1_BASE, I2C_CON, 2
>
>     I2C_WAIT_BY_STOP
>
>     //------------------------------------------------------------------
>     //inizializzazione IOEXP 1
>     
>     //indirizzo slave
>     MOV r1.w0, IO_EXP1            
>     SBCO r1.w0, I2C1_BASE, I2C_SA, 2
>
>     //n. byte da spedire gia' impostato
>
>     //riempie FIFO
>     MOV r1, IO_EXP_IODIRA | 0x00000000        //tutti pin come uscita
>     SBCO r1.b0, I2C1_BASE, I2C_DATA, 1
>     SBCO r1.b1, I2C1_BASE, I2C_DATA, 1
>     SBCO r1.b2, I2C1_BASE, I2C_DATA, 1
>
>     //comando scrittura
>     MOV r1.w0, I2C_CMD_ENABLE | I2C_CMD_TX | I2C_CMD_START | I2C_CMD_STOP
>     SBCO r1.w0, I2C1_BASE, I2C_CON, 2
>
>     I2C_WAIT_BY_STOP
>
>
>     //------------------------------------------------------------------
>     //ciclo rinfresco I/O
>
> _LOOP:
>  
>     //------------------------------------------------------------------
>     //legge ingressi
>     
>     //indirizzo slave
>     MOV r1.w0, IO_EXP0            
>     SBCO r1.w0, I2C1_BASE, I2C_SA, 2
>
>     //n. byte da spedire
>     MOV r1.w0, 1            
>     SBCO r1.w0, I2C1_BASE, I2C_CNT, 2
>
>     //riempie FIFO
>     MOV r1, IO_EXP_GPIOA
>     SBCO r1.b0, I2C1_BASE, I2C_DATA, 1 
>  
>      //comando scrittura
>     MOV r1.w0, I2C_CMD_ENABLE | I2C_CMD_TX | I2C_CMD_START
>     SBCO r1.w0, I2C1_BASE, I2C_CON, 2
>
>     I2C_WAIT_BY_COUNT
>  
>      //n. byte da ricevere
>     MOV r1.w0, 2            
>     SBCO r1.w0, I2C1_BASE, I2C_CNT, 2
>
>      //comando lettura
>     MOV r1.w0, I2C_CMD_ENABLE | I2C_CMD_RX | I2C_CMD_START | I2C_CMD_STOP
>     SBCO r1.w0, I2C1_BASE, I2C_CON, 2
>
>     I2C_WAIT_BY_STOP
>
>     //legge i byte ricevuti
>     LBCO r2.b1, I2C1_BASE, I2C_DATA, 1 
>     LBCO r2.b2, I2C1_BASE, I2C_DATA, 1 
>
>     //------------------------------------------------------------------
>     //scrive uscite
>
>     //indirizzo slave
>     MOV r1.w0, IO_EXP1            
>     SBCO r1.w0, I2C1_BASE, I2C_SA, 2
>
>     //n. byte da spedire
>     MOV r1.w0, 3            
>     SBCO r1.w0, I2C1_BASE, I2C_CNT, 2
>
>     //riempie FIFO
>     MOV r2.b0, IO_EXP_GPIOA
>     SBCO r2.b0, I2C1_BASE, I2C_DATA, 1 
>     SBCO r2.b0, I2C1_BASE, I2C_DATA, 1 
>     SBCO r2.b0, I2C1_BASE, I2C_DATA, 1 
>
>     //comando scrittura
>     MOV r1.w0, I2C_CMD_ENABLE | I2C_CMD_TX | I2C_CMD_START | I2C_CMD_STOP
>     SBCO r1.w0, I2C1_BASE, I2C_CON, 2
>
>     I2C_WAIT_BY_STOP
>     
>     //------------------------------------------------------------------
>     LBCO r2, CONST_PRUDRAM, 0, 4
>     ADD r2, r2, 1
>     SBCO r2, CONST_PRUDRAM, 0, 4    
>     
>     //------------------------------------------------------------------
>     //esce dal ciclo e se il flag di uscita nella ram condivisa e' azzerato
>     LBCO r2, CONST_PRUDRAM, 4, 1
>     QBNE _LOOP, r2.b0, 0
>
> _EXIT:
>     //invia all'host la notifica di programma completato
>     MOV R31.b0, PRU0_ARM_INTERRUPT+16
>
>     HALT
>

-- 
For more options, visit http://beagleboard.org/discuss
--- 
You received this message because you are subscribed to the Google Groups 
"BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to