I2C on PRU: how to?

Hi everyone. My name is Pedro Bertoleti and I’m from Brazil.

I’m learning about the PRUs on BeagleBone (I’m using BeagleBone Black board) and I wanna read IMU and another I2C sensors in PRU firmware (to be able to implement some motion algorithms and stuffs like that in PRU firmware, due to its real-time scope).

However, I’m not sure on how to use I2C in PRU. Per my understanding:

A) PRUs have no hardware dedicated to I2C (nor SPI)
B) I’ve seen some SPI examples with PRU on Internet, however in all of them SPI communication was made using bit-bang technique.

So, would you help me answering the following questions?

  1. Do I need bit-banging to communicate PRU to I2C devices? I mean, isn’t there another way to use I2C in PRU?
  2. If answer above is yes, is there an way to change gpio direction (input to outut and vice versa) inside PRU firmware? I ask this because, as I read so far, only config-pin (Linux side) can “enable” a gpio to PRU and set its direction, and glio direction change will be needed if I need to make I2C using bit-bang technique.

Please, would anyone shed some light on it?

Thanks in advance.

Hello Pedro

Is their a block diagram that shows the Interconnect peripherals in TRM?That used to be pretty standard in TRM and answers #1

I avoid Linux so I can’t answer #2 but I’m pretty sure this question was asked before in this group.

Lastly refine your Google arguments I did find this but it may be for bare bones system.

https://e2e.ti.com/support/processors/f/791/t/458311?AM335x-PRU-access-to-I2C-and-other-peripherals-on-L4-PER-bus

I would start with the block diagram for L4

Lastly Mark Yoder a professor who teaches embedded Linux has various tutorial and cookbooks. He’s very gifted and his documents are clearly written and updated. Dig around their last after understanding what’s possible would be my approach.

You know what they say about about too many cooks in the Kitchen Pedro?

They spoil the soup :thinking::hugs:

If you do some research and then narrow down the specifics you won’t be misled

Hopefully I’ve offered something positive to help you.

Mark

Mark, thanks!

Pedro greetings.

NpThe discussion in this group about #2 should be helpful as I remember there were conflicting answers about pin mixing after Linux is running. I’ll see if I can find the post later it may have been another pin or not i2c but concept was there. try and Google beagleboard group PRU I2C pin mux.
You still have issue if Linux is using this pin but not insurmountable
Let us know how you are doing I’ll do some digging later to

Cheers

Hello Pedro

The thread I found turned into a big argument it looks like thats why I remembered it and made a reference to too many cooks giving advice. I will provide link but I am having trouble finding entire thread in the mail archive

[beagleboard] Re: Problems Reconfiguring GPIO’s

[

[beagleboard] Re: Problems Reconfiguring GPIO’s

](https://www.mail-archive.com/beagleboard@googlegroups.com/msg57435.html)
As you see some members active in group were postulating and I don;t want to start trouble I wanted to help but I was afraid the couldd result in bad advise.

Start with Part 1 and convince yourself its possible by finding some PRU code for I2C that pretty much means its possible at least you will learn about PRUs start simple. Feel free to start another thread but check github and Marks PRU stuff Ill be watching for updates I would like to be more helpful.

Did you find the L3 Per block diagram ?

Best wishes my friend keep plugging!

Mark

Mark, thanks!

Hi Mark.

First of all, thank you for all the information. I’ve learnt a lot.
After making some reads about PRU in AM335x TRM, I’ve confirmed PRU can access various SIP peripherals, including the I2C interfaces (thank god! Bit-banging an I2C would be boring as hell).

Per my understanding (and accordingly to pru cook book), I2C2 (for example) is mapped into 0x4819C000 memory address. Also, configuration registers must be set in another registers to make I2C2 work properly (I’m trying to understand them now).

Please, correct me if I’m wrong:
If I write/read data from 0x4819C000, I’ll be able to communicate via I2C2 inside PRU, right?

Also: once I2C2 is up and running in Linux side (= it has been configured at some time during bootloader initialization), is it enough for me to yse I2C2 in PRU by just writting and reading the address 0x4819C000?

Sorry if I understood it wrong.

Best Regards,
Pedro Bertoleti

Hello Pedro

I’d have to check exact addresses but you have the correct idea. If you use Linux to set muxing so pins are I2C this eliminates investigation of that’s even possible from PRU just have Linux do it.

This then leaves

Also, configuration registers must be set in another registers to make I2C2 work properly

Then you read and write to a register as you said to transmit or receive

The config register’s usually allow polled or interrupt to be generated.

Polling is probably easier

The PRU examples may have both I haven’t looked at the code.

The important part is understanding exact adresses of all registers and which bits are being polled or checked.

You look at the code and header files and calculate what addresses are being Access. Look in TRM see address code using and say ok he’s polling for data on bit 5 or oh here he’s transmitting a byte.

Of course you need a device wired up to communicate.

Probably the simplest test is to read a status register from the slave device that contains known data from it’s data sheet.

You could code that by modify an example provided in cookbook.

Just steal all the init config code and modify example to poll forever reading the slave status register for known value if you get that working first time I’d be proud.

It’s more than likely this code will not work as Linux didn’t mux like you wanted let be positive.

Of course simplest way of it all works is you use exact what he’s using for linux in cookbook and same slave device and wire it correctly

It’s worth buying everything he has exactly same hardware who knows maybe then he can help​:crazy_face::thinking: if you post.

To me the important parts are understanding exactly what the PRU examples are doing specific to register addresses and correlation that the addresses match the TRM and you understand the bits being manipulated in registers by cross reference TRM.

Every device driver uses same idea.

The power of this is then you can write an I2C device driver for ARM core as well of course address change in TRM

To be honest a device driver on a bare Bones ARM core is much more straight forward.

Using PRU now you have to decipher whether linux set up I2C mux correctly on ARM.

That’s really backwards having 2 processor’s configuring a device. Especially the way it’s done in Linux

Now factor in you need the data to be shared outside the chip you have all the Linux virtual address crap it’s a mess.

Did you know they have SOC same arm cores plus DSP. both cores can run in hard realtime fast no PRU both DSP and and ARM can use I2C and share Data in shared memory very simple to understand and fast you know why?
You don’t have an albatross called Linux on the arm :thinking:
The downside is these RTOS cost $$$$$ or using bare Bones you need device driver’s

Linux is good but it’s meant for Stuff that’s not hard realtime that’s probably why the PRU was added.

Anyway you have what you have to use so better to be positive and work through it unfortunately I know zero about DTS dtbo etc etc.
I do know uboot.
Let’s accumulate as much I2C c code as possible for BBB is good.

You do know they may have both interrupt and polled I2C examples for ARM and maybe PRU in starterware?
These are Best to understand how I2C is done as far as address of registers and values in config register’s.

I’ll do some digging for c code examples it be good refresher course for me. I did this for 32 year’s I’m old hahaha I miss it.

Keep us posted :relaxed:

Hi Mark.

Here follows some more interesting information found on TRM:

  • The address 0x4819C000, referred as I2C2 peripheral in .cmd file (in PRU examples) really refers to I2C2 in TRM:
    i2c2_addr.jpeg

  • Checking I2C2 registers, I’ve found its data register, as shown below:

i2c_data_reg.jpeg

Therefore, i came to the following conclusions:

a) The full address to the I2C2 data register is 0x4819C000 + 9C = 0x4819C09C
b) Once I2C2 is configured by Linux and/or bootloader as default in my case (I can successfully use I2C2 from Linux side in BeagleBone Black), I don’t need to set it up again in pru. I understand that if I write and read the bytes 7:0 from 0x4819C09C memory address, I’m actually writing and reading from an I2C device wired to I2C2 interface

Do you think a and b conclusions are correct? This PRU stuff is new to me, sorry if i’m being annoying.

Best Regards,
Pedro Bertoleti

You definitely don’t need to redo muxing that linux does. My interest in this is whether the I2C config register’s can be setup from PRU looking at tables and .cmd file comments leads me to believe you can. It’s possible muxing isn’t allowed by PRU in your case you don’t care.

Now you have the science from TRM. Compare code address in header files and c code to Match address in your new question or just run the code if it doesn’t work then calculate .

It’s always better to predict from TRM addresses using a memory map in TRM. As you noted addresses are different from ARM I2C and PRU I2C.

I would draw a memory map with predicted PRU I2C range, shared memory ranges, PRU RAM anything relavent.

You will need this to use printf dump’s if it doesn’t work. I always did this first.

You are progressing logically, slowly and methodically I’m proud you will be great engineer!!

Mark

i2c_data_reg.jpeg

i2c2_addr.jpeg

Pedro

This looks like a great place to start for further research after trying a canned cookbook example
I am assuming you have custom devices either way this looks very good at a glance

BeagleBoard/GSoC/PRU I2C-SPI master furtherwork - GSoC 2018 - eLinux.org

[

BeagleBoard/GSoC/PRU I2C-SPI master furtherwork - GSoC 2018 - eLinux.org

](https://elinux.org/BeagleBoard/GSoC/PRU_I2C-SPI_master_furtherwork_-_GSoC_2018)

Keep us updated

Sincerely

Mark

Hi Mark.

Here follows some more interesting information found on TRM:

  • The address 0x4819C000, referred as I2C2 peripheral in .cmd file (in PRU examples) really refers to I2C2 in TRM:
    i2c2_addr.jpeg

  • Checking I2C2 registers, I’ve found its data register, as shown below:

i2c_data_reg.jpeg

Therefore, i came to the following conclusions:

a) The full address to the I2C2 data register is 0x4819C000 + 9C = 0x4819C09C
b) Once I2C2 is configured by Linux and/or bootloader as default in my case (I can successfully use I2C2 from Linux side in BeagleBone Black), I don’t need to set it up again in pru. I understand that if I write and read the bytes 7:0 from 0x4819C09C memory address, I’m actually writing and reading from an I2C device wired to I2C2 interface

Do you think a and b conclusions are correct? This PRU stuff is new to me, sorry if i’m being annoying.

Best Regards,
Pedro Bertoleti

1 Like