Tuesday, May 30, 2023

Digging deeper on the porting challenges of Raspberry Pi Nano based code to ARM Intel system

The library of C code to make use of the LCD monitor and touch screen is provided along with the module as a convenience, but it was written for use on a Raspberry Pi Nano system. This has its own unique way of communicating with SPI and of controlling digital IO pins, in some ways like an Arduino and in some ways even a bit odder. 

The library calls are not standard C calls and have some functions that don't map to usual SPI drivers or libraries. However, the weirdness goes deeper. The chip itself does not have a standard SPI slave chip, just as the Pi does not implement an SPI master like other systems. This allows the writers of the library to do things that would not be accomplished with more standard SPI endpoints. 

The LCD module has a 16 bit deep shift register which is reset when the slave select is activated and it then passes in the MOSI data bits at each clock cycle. Every 16 clock cycles it generates a strobe to output the register data in parallel which is wired to the LCD controller. Thus we could send a continuous stream of 16 bit words with slave select held low and the LCD controller chip would take those 16 bit parallel words one at a time at each word boundary.

The software library writes data as two 8 bit SPI transfers with the slave select held across the pair. This works properly with the hardware in the module as it doesn't care that the PI thinks it is sending 8 bit bytes. 

However, the library writes commands as a single 8 bit SPI transfer. This apparently works fine with the PI but I still don't understand how the hardware in the module ever passes that along to the LCD controller. That is, the counter doesn't get up to 16 therefore it never strobes out the data from the serial in parallel out shift register and the LCD controller never sees the command byte. 

I have to conclude that since the PI software is dropping slave select after a single byte is written for commands, it somehow knows to send a second byte of zeroes to complete the count. That is the only explanation as otherwise this could never work.

Now, in the Intel/Altera world with standard SPI hardware, the controller conforms to the Motorola specification that defined SPI. One of the consequences is that the behavior of the master sending data is different for one of the four modes of SPI transmission - Clock polarity of 0 and Clock phase of 0 - compared to the mode with polarity 1 and phase 1. The specification is mute on the behavior for the modes 1/0 and 0/1. 

In this mode of 0/0, the master will drop the slave select signal between each word in spite of the fact that we are holding it steadily asserted. This depends on the configuration of the SPI link - which can be 8 bit or 16 bit words - but it is fixed when you configure the link and enable it until it is subsequently disabled. In the modes 1/1 the slave select signal we set is not interfered with by the controller logic. 

The hardware in the LCD module is set up for mode 0/0. Unfortunately the usage by the library is not compatible with that. Sometimes they send 8 bits and drop slave select, sometimes they send 16 bits and drop slave select, and sometimes they send a continuous stream of 16 bit words with slave select held until the end of the last word. The select behavior they depend upon is appropriate for 1/1 mode but the hardware is working in 0/0 mode. 

The solution is to set up an inverter for the SCLK (clock) signal and tell the master we are operating in the complementary mode. In our case, configuring our master as mode 1/0 but inverting the clock produces signals at the hardware in the slave that are the same as 0/0.  Unfortunately that mode does NOT support continuous transfer, only one word before CS is dropped. 

If I go with the 16 bit word length and mode 0/0, as I have already configured the system, I can resolve the problem with short commands by ensuring I send a dummy byte to fill out the word. The only thing I won't be able to handle is a true continuous transfer where slave select stays asserted through multiple words. 

I will have to carefully study the LCD controller manual to be certain that it will work properly with bursts of words separated by slave select rather than the continuous transfer envisioned by the library. 

COINCIDENTAL DISCOVERY THAT WILL REQUIRE SOME REDESIGN

While diving deeply into this mess with SPI, I came to understand that my four slave select signals don't switch when I assert them; they are activated when the transmit buffer has a word or more in it. Since I was using select 3 and 4 for the LCD reset and the LCD Data/Command mode signals, I expected they would be passed through at all times. They won't. 

Thus when I think I am resetting the LCD module by setting that slave select signal, nothing would go to the module unless I was transmitting data at the same time. If it was only an issue with reset, I could just send a dummy word to that phantom device associated with the slave select bit. However, I need the LCD Data/Command signal to be active while I am transmitting data to the LCD controller, thus when I have the LCD select bit asserted. This asserts two slave selects simultaneously and I certainly can't transmit dummy data while the LCD controller is listening. 

I have to rethink how I route these two signals. More later when I make a decision. 

No comments:

Post a Comment