Exposing the PRU as an I2C,SPI,UART device

Hello everyone,
My name is Vaibhav Choudhary(Chanakya_vc on the IRC ).
In this mail,I have summarised ,what I have understood about the project and also have broken down the project into weekly tasks.I have also talked about what I would in the pre-coding period.I have also prepared a Gantt chart for the project,which may help the mentors better visualize my project time line.This time line might have missed some key aspects of the project.Or there could certain gaps in my understanding of the project.I would request all the mentors guiding me on the IRC to please point out those and correct me wherever required.Also Wherever I have had a doubt I have highlighted that.I would request the mentors to answer those as well.

Bitbanging an SPI or/an I2C device in Linux leads to a lot of problems.It consumes a lot of valuable CPU cycles.And since Linux is an non-preemptive OS(And not an RTOS),once we start bitbanging,other important tasks that require CPU time would suffer.Thus,there are a lot of software overheads in doing the same.
To avoid this on the BBB,we could offload the task of bitbanging I2C,SPI,UART, to the PRU.The PRU is a separate core and,hence,not affected by the Linux Scheduler. Hence the motivation for exposing the PRU as an I2C,SPI,UART device comes from the fact that they would be no software overheads in doing it and hence,we would gain extra serial interfaces without wasting valuable CPU cycles in bitabanging.

This project involves writing Device Tree Overlays,Device Drivers and PRU firmware code for Bitbanging I2C,SPI and UART.

  1. The DTO would instantiate the PRU to behave as SPI,UART,I2C ,by defining the necessary parameters.Apart from that DTO would initiate modprobe for the required driver and also load the firmware onto PRU(Still researching on how to write DTO).

  2. The device driver would provide an interface between the userland and the shared memory.A device file gets exposed to the userland which allows us to write or receive data from the shared memory.For example in I2C,the PRU would basically be assigned a I2C adapter number and then would act as a normal device file to which data can be written.The device drivers would be dependent on the rproc driver. And when the DTO would initiate modprobe to load the necessary driver rproc would show up in modules.dep.

  3. The firmware would contain the code for bitbanging I2C,SPI,UART. (This will be specific to the particular protocol.)For example in SPI,the shared memory would act as SPI shift register and we would code to generate SCLK(or recieve data from a master in case of slave mode).We would have to decide on the clock polarity and clock phase. And in each case the edge of the clock in which sampling takes place would be different.

The Gantt Chart:Please visit this link to see the Gantt chart that I have prepared for the time line.
This is my first attempt in doing so. I will try to make a more comprehensive one for the proposal.The time line that I have in mind is explained below:

For achieving the above three steps(and completing the project), in the pre-coding period(20/3/16-21/5/16) I would be undertaking the following tasks:

  1. Set up the required toolchains for firmware code(TI compiler)

  2. Revisit Assembly coding and control LED’S through the PRU.

  3. Familiarize myself with writing Drivers and complete a hello world driver before the 10th of April.

  4. Familiarize myself with DTO and how to compile them using DTC’s.Also look at how to edit uEnv.txt to load the required overlay.

  5. Look at the various code samples that exist for bitbanging I2C,SPI,UART.
    Familiarize myself with error correction techniques in I2C(Simultaneous transmission by two masters) and UART.Also look at various other details of I2C and UART(For example concept of general call addresses and receiver acknowledging each byte transmitted in I2C )
    Look at the concept of Daisy chaining in SPI.
    The project broken up into weekly tasks is as follows:

  6. Week 1(23 May -29 May)(EXAMS IN COLLEGE)
    -Start with the firmware code for I2C.

2. Week 2(30 May-4 June)

-Complete the code for Bitbanging I2C.As discussed this would include compiling the firmware with TI’s compiler
-Resolve collision issues(simultaneous transmit by two masters,if PRU is to be used as a master interface)
-General call address
-Start with coding Driver for I2C.

3. Week 3(06 June -11 June)
-Complete Driver for I2C.The driver should give the PRU an I2C interface number and expose an I2C dev file.For this I would be looking at this link(as given to me by alexhiam):
https://www.kernel.org/doc/Documentation/i2c/dev-interface
-Start and finish the device tree overlay for I2C. I understand that this could simply be a modification of the DTO that already exists for Beaglelogic?(still researching on it)
-Test the PRU in I2C slave/master mode.

4 .Week 4(13 June-18 June )

-Start coding to implement bitbanging SPI.This would include:
-Researching into the standards that are implemented regarding clock phase and polarity.
-Looking at transfer of dummy bytes inorder to initiate a transfer from a slave interface.Similarly the master ignoring bytes form slave incase of a write operation.
-If coding for SPI master interface,I believe that multiple CS would be required.So researching into the exact process of choosing a slave to transmit.(I believe that the CS for that particular slave goes low.But how does the user choose which slave to transmit to.I don’t think there are addresses in SPI?
And moreover,how will the firmware or DTO decide on the number of CS pins it requires.There would be a test required to determine no. of slaves and automatically decide on the number of CS pins?)

5. Week 5(20 June-25 June)
-Compile the firmware code for SPI
-Start with the driver for SPI.
-This would expose a spidev file to the userland.This spidev file would allow users to write to the shared memory.Shared memory in our case would behave as the SPI shift
register.I would be looking at this link for that: https://www.kernel.org/doc/Documentation/spi/spidev
-Also would allow users to read the bytes that would come in the register from the slave.This would be dependent on the remoteproc(still researching on it.)

6.Week 6(27 June -2 July)
-Complete and compile the driver for SPI.
-Start with the DTO for SPI.(In my understanding this would basically involve modifying the one that already exists for Beaglelogic and define which pins would be
MISO,MOSI,SCLK,CS. I am still researching regarding DTO’s)
-Compile DTO and test PRU as SPI master/slave mode.

7 .Week 7(4 July-9 July)
-Start with bitbanging UART.I am still researching regarding UART.
What I do not understand is whether we would be using RS-232C,RS-485,RS-422? And would we required an external level shifter to convert serial transmissions to
and from RS-232C levels?(I am not too sure about it)

8. Week 8(11 July -16 July)
-Start with driver for UART(still researching on that)

9.Week 9(18 July-23 July)
-Start with DTO for UART(still researching on it)
-Compile DTO and test UART on PRU.

10. Week 10(25 July -5 August)
-Documentation and Writing Code examples.

11. 6 August -20 August:Free time to cope with anything unexpected.

The last two weeks have been left to cope with unexpected delays and to clean up existing code.

Also the two PRU’s would not be able to work independently,like one as a I2C interface and the other as an SPI at the same time right?(Even if I write separate DTO’s for both the PRU’s?)

This plan is by no means complete.I hope that the mentors would correct me wherever I have gone wrong.

Thanking-You
Vaibhav Choudhary
NSIT,University of Delhi.

Hi,

Comments in line.

Hello everyone,
My name is Vaibhav Choudhary(*Chanakya_vc on the IRC *).
In this mail,I have summarised ,what I have understood about the project
and also have broken down the project into weekly tasks.I have also talked
about what I would in the pre-coding period.*I have also prepared a Gantt
chart for the project,which may help the mentors better visualize my
project time line*.This time line might have missed some key aspects of the
project.Or there could certain gaps in my understanding of the project.I
would request all the mentors guiding me on the IRC to please point out
those and correct me wherever required.Also Wherever I have had a doubt I
have highlighted that.I would request the mentors to answer those as well.

Bitbanging an SPI or/an I2C device in Linux leads to a lot of problems.It
consumes a lot of valuable CPU cycles.And since Linux is an non-preemptive
OS(And not an RTOS),once we start bitbanging,other important tasks that
require CPU time would suffer.Thus,there are a lot of software overheads in
doing the same.
To avoid this on the BBB,we could offload the task of bitbanging
I2C,SPI,UART, to the PRU.The PRU is a separate core and,hence,not affected
by the Linux Scheduler. Hence the motivation for exposing the PRU as an
I2C,SPI,UART device comes from the fact that they would be no software
overheads in doing it and hence,we would gain extra serial interfaces
without wasting valuable CPU cycles in bitabanging.

This project involves writing Device Tree Overlays,Device Drivers and PRU
firmware code for Bitbanging I2C,SPI and UART.

1. The DTO would instantiate the PRU to behave as SPI,UART,I2C ,by defining
the necessary parameters.Apart from that DTO would initiate modprobe for
the required driver and also load the firmware onto PRU(Still researching
on how to write DTO).

Given the length of GSoC, properly designing this part may require more time
then available. In addition, having DT (device tree support) is what you be
looking at. Overlays are another way to add new features to a fixed DT.

IMO - having this as a secondary goal might be viable.

2. The device driver would provide an interface between the userland and
the shared memory.A device file gets exposed to the userland which allows
us to write or receive data from the shared memory.For example in I2C,the
PRU would basically be assigned a I2C adapter number and then would act as
a normal device file to which data can be written.The device drivers would
be dependent on the rproc driver. And when the DTO would initiate modprobe
to load the necessary driver rproc would show up in modules.dep.

If this is done through the proper APIs, you do not need to worry about the
userland pieces. There are standard APIs for exposing I2C, SPI, and UART
devices.

3. The firmware would contain the code for bitbanging I2C,SPI,UART. (This
will be specific to the particular protocol.)For example in SPI,the shared
memory would act as SPI shift register and we would code to generate
SCLK(or recieve data from a master in case of slave mode).We would have to
decide on the clock polarity and clock phase. And in each case the edge of
the clock in which sampling takes place would be different.

* The Gantt Chart:Please visit this link to see the Gantt chart that I have
prepared for the time line.
<https://app.smartsheet.com/b/publish?EQBCT=100f1e2a2cd9410c9900b8cfc10a2a2e
>*This is my first attempt in doing so. I will try to make a more
comprehensive one for the proposal.The time line that I have in mind is
explained below:

For achieving the above three steps(and completing the project), in the
pre-coding period(20/3/16-21/5/16) I would be undertaking the following
tasks:
1. Set up the required toolchains for firmware code(TI compiler)
2. Revisit Assembly coding and control LED'S through the PRU.
3. Familiarize myself with writing Drivers and complete a hello world
driver before the 10th of April.
4. Familiarize myself with DTO and how to compile them using DTC's.Also
look at how to edit uEnv.txt to load the required overlay.
5. Look at the various code samples that exist for bitbanging I2C,SPI,UART.
Familiarize myself with error correction techniques in I2C(Simultaneous
transmission by two masters) and UART.Also look at various other details of
I2C and UART(For example concept of general call addresses and receiver
acknowledging each byte transmitted in I2C )
Look at the concept of Daisy chaining in SPI.

Please clarify what do you mean by daisy chaining in SPI?

The project broken up into weekly tasks is as follows:

1. *Week 1(23 May -29 May)(EXAMS IN COLLEGE)*
      -Start with the firmware code for I2C.

*2. Week 2(30 May-4 June)*
     -Complete the code for Bitbanging I2C.As discussed this would include
compiling the firmware with TI's compiler
           -Resolve collision issues(simultaneous transmit by two
masters,if PRU is to be used as a master interface)
           -General call address
     -Start with coding Driver for I2C.

It looks like you need to clearly define what your I2C master will be capable
of.

*3. Week 3(06 June -11 June)*
     -Complete Driver for I2C.The driver should give the PRU an I2C
interface number and expose an I2C dev file.For this I would be looking at
this link(as given to me by alexhiam):
      https://www.kernel.org/doc/Documentation/i2c/dev-interface

It might be more useful if you test this against standard kernel devices.
Timing via the userland debugging interface can be skewed.

     -Start and finish the device tree overlay for I2C. I understand that
this could simply be a modification of the DTO that already exists for
Beaglelogic?(still researching on it)
     -Test the PRU in I2C slave/master mode.

*4 .Week 4(13 June-18 June )*

     -Start coding to implement bitbanging SPI.This would include:
          -Researching into the standards that are implemented regarding
clock phase and polarity.
          -Looking at transfer of dummy bytes inorder to initiate a
transfer from a slave interface.Similarly the master ignoring bytes form
slave incase of a write operation.
          -If coding for SPI master interface,I believe that multiple CS
would be required.So researching into the exact process of choosing a slave
to transmit.
*(I believe that the CS for that particular slave goes low.But
how does the user choose which slave to transmit to.I don't think there are
addresses in SPI? And moreover,how will the firmware or DTO
decide on the number of CS pins it requires.There would be a test required
to determine no. of slaves and automatically decide on the number of CS
pins?)*

*5. Week 5(20 June-25 June)*
      -Compile the firmware code for SPI
      -Start with the driver for SPI.
          -This would expose a spidev file to the userland.This spidev file
would allow users to write to the shared memory.Shared memory in our case
would behave as the SPI shift
           register.I would be looking at this link for that:
https://www.kernel.org/doc/Documentation/spi/spidev
          -Also would allow users to read the bytes that would come in the
register from the slave.This would be dependent on the remoteproc(still
researching on it.)

*6.Week 6(27 June -2 July)*
      -Complete and compile the driver for SPI.
      -Start with the DTO for SPI.(In my understanding this would basically
involve modifying the one that already exists for Beaglelogic and define
which pins would be
       MISO,MOSI,SCLK,CS. I am still researching regarding DTO's)
      -Compile DTO and test PRU as SPI master/slave mode.

Similar to the I2C - please define the capabilities of the SPI device you want
to implement.

* 7 .Week 7(4 July-9 July)*
      -Start with bitbanging UART.I am still researching regarding UART.

*What I do not understand is whether we would be using
RS-232C,RS-485,RS-422? And would we required an external level shifter to
convert serial transmissions to and from RS-232C levels?(I am not
too sure about it)*

*8. Week 8(11 July -16 July)*
      -Start with driver for UART(still researching on that)

Similar to above, please define the capabilities of the UART. You might also
want to work out the math to see what rates you can do.

*9.Week 9(18 July-23 July)*
     -Start with DTO for UART(still researching on it)
     -Compile DTO and test UART on PRU.

*10. Week 10(25 July -5 August)*
    -Documentation and Writing Code examples.

*11. 6 August -20 August:Free time to cope with anything unexpected.*

The last two weeks have been left to cope with unexpected delays and to
clean up existing code.

*Also the two PRU's would not be able to work independently,like one as a
I2C interface and the other as an SPI at the same time right?(Even if I
write separate DTO's for both the PRU's?)*

This plan is by no means complete.I hope that the mentors would correct me
wherever I have gone wrong.

Things to consider for the devices you are implementing:
1. Slave/Master mode
2. Speed to support
3. Multiple instances?
4. Speed it can work at.
5. Limitations on the implementation.

One thing you have not addressed is how do you plan to handle the
communications between the PRUSS and the ARM. Different options may have
different implications such as overheaad, power usage, etc.