PSoC 6, FreeRTOS & SSD1306 OLED Display


This week I have been working with my friend Hassane El Khoury on his hobby project which has the SSD1306 in it. [if you want to know more about the project, leave a comment and maybe he will answer the question].  I have been helping him get a number of things going including this display which I have written about before.  This article describes the integration of the SSD1306 OLED Display into his project with the PSoC 6 & FreeRTOS.

Firmware Architecture

Hassane started his career as an Automotive System Designer, then he worked as an Applications Engineer, so he has “mad” skills in this area.  He is building his project with a PSoC 6 and is heavily using FreeRTOS (which is new for him).  He has been distracted with some other thing the last few years, so I have been serving as a consultant on the latest PSoC stuff to smooth the learning curve.  In this case PSoC6, FreeRTOS and the SSD1306 OLED Display.  I have only used the SSD1306 OLED Display with PSoC 4 and WICED, but I ASSUMED (incorrectly assumed… which I will talk about in the next article) that there would be no problems making it work in that environment.

Hassane is all about reuse and he had copied the design of this section of his project from my article on using queues with FreeRTOS.  It looks like this.

  1. There is a task that manages the I2C and talks directly to the SCB hardware and the I2C devices
  2. There is a task that manages the OLED

ssd1306 oled display architecture

Originally the OLED task was talking directly to the I2C via the SCB (the red line on the picture).  Remember from the article on the U8G2 library, the hardware abstraction layer looks like this.  Basically it

  1. Sends an I2C Start at the start of the U8G2 transaction
  2. Sends an I2C Stop at the end of the tranaction
  3. Send the number of bytes called for.

The problem with this design is that it takes over the I2C hardware and requires exclusive control.  Moreover, it leaves you program hung while the transaction is happening.  To solve this problem, there are three options

  1. “Assign” the SCB block to the exclusive use of this task (makes it hard to share with other I2C devices)
  2. Create a mutex for the SCB.  This will work, but it will not allow the task to “queue” transactions and move on
  3. Create a task to manage the SCB with a queue (the option that Hassane chose)

The I2C message queue holds complete transactions.  Each transaction (which he called I2Cm_transaction_t) looks like this:

In order to fix the the HAL you just sets up a transaction at the start of the task:

Then queue up the bytes into a buffer, and flush the buffer when the “U8X8_MSG_BYTE_END_TRANSFER” message comes

SSD1306 OLED Display

Now, the short block of test code works perfect:

And I get a nice output (I wonder what a “Killer Mustang” is?)

In the next article Ill talk about the SS1306 and a problem that I created for myself.