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. 


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. 

Drawing on the LCD screen to test functions I need - part 1


Serial Peripheral Interface (SPI) links consist of a signal running from the controlling (formerly master) side to the controlled (formerly slave) entity, called MOSI, a second signal in the reverse direction called MISO, a clock produced by the controlling side and a select signal for each controlled entity. 

We have two controlled entities, one for the LCD module and the other for the touch pad interface atop the screen. We can read or write to the entity by asserting its select line and then sending or receiving 16 bit words serially over MOSI/MISO. It is up to each controlled device what the data means - the protocol and bit definitions are up to the designer of that device.

I have example libraries from the company that sold the LCD Module, which I had to convert from Raspberry Pi Nano to classical Linux SPI and the interface used on the Cyclone V at the heart of my DE10-Nano board. I think I have this properly converted but it is possible that I introduced errors. 

In addition to the SPI link the LCD module has additional signal wires. One is used to define whether a particular word being transmitted is a command or data, the distinction being relevant to the way the LCD module works. Another is a reset signal that puts the LCD module in a known state. Lastly the touch controller will activate its interrupt line whenever the user touches the screen, thus that is another signal wire being used. 

If I have the SPI link configured properly, which is a set of choices that must be in sync between controlling and controlled entities, then basic data will seen or transmitted from the controlled entities properly. Clock phase, clock polarity, baud rate and word size are among the parameters that must match. 

Just talking to the devices is not enough, I have to send command and data streams that are meaningful to them in order to draw on the screen or read coordinates of the last touch on the pad. This is another area where my changes may have introduced bugs. 

Lastly, I have to correctly understand the addressing and rules for drawing characters or shapes on the screen. Is a vertical address the middle of a character, the top or the bottom? Same kind of question for horizontal addresses. Will I draw the text from left to right, or at a right angle or upside down? This part is not clearly spelled out in any of the documentation; I had to impute it from the code. This requires verification. 

Thus my first test programs will be writing text at a chosen location to verify the addressing and direction. It will draw a shape for the same purposes. I will touch a few points and check that a) I get an interrupt and b) the coordinates returned match my mental picture of the screen layout. All these tests will first have to test the lower levels, from the basic parameters upwards and validate all my conversion changes to the libraries. 


To test I will need to hook up ten jumpers from the LCD Module to the DE10-Nano board. Using an oscilloscope as well as other diagnostic methods I can start to check out the communications from the most basic level on up, which might need to be done before a single thing appears on the LCD screen.  

With it all wired up and a good test program running, I saw that it stalled inside the LCD initialization call. I did some tracing and it appears that a routine to set up the registers for the module does special command to request the module ID - but it is blocking so we are not completing an SPI transaction. 

Next up I will double check polarities of the various signals to the module and then hook up the scope to see what is actually happening on the wires. Don't yet know what kind of SPI mismatch or misconfiguration or other error is at the root of this, but I did expect to have to fight through this before I was actually debugging my GUI screen images. 

Sunday, May 28, 2023

Tested module to extract and list the virtual 2315 cartridge files on the SD Card


The user of this system will put virtual 2315 disk cartridges as files in a specific directory of the SD Card on the DE10-Nano board, allowing them to select one of them to virtually mount on the IBM 1130 disk drive. I have configured the product initially to support up to 128 cartridge images, but this is configuration from a header file if an institution every needs to increase the capacity.

The user interface program displays 20 of the file names at a time on the LCD screen, allowing the user to move the selection point up or down by pushing Up or Down buttons on the screen. Think of this as a window of 20 entries that can slide up and down across the entire list of installed files. If the user scrolls past the bottom or top of the screen we will shift the window down or up to move that window. 

This module - opencarts - looks at the directory and extracts the file names of all the virtual disk files. It ensures they are files of the correct size and makes other checks before adding them to an in-memory array of file names. At any point in time, one of the twenty lines of file names is highlighted, which will be the cartridge loaded if the user touches the Select button on the screen. 

The display of twenty names from the list based on the history of Up and Down button pushes is accomplished by another module - showscreen - using the list of filenames that was populated by opencarts


I dashed off a small test program to verify that opencarts worked correctly. I first ran it with no virtual files on the SD Card, to verify that it handled the edge case. Eight disk images were installed and showed up correctly in the list. 

Friday, May 26, 2023

Verifying key functionality with small focused test programs, part 5


I selected the signal HPS_I2C1_SCLK found on the LTC connector pin 11 as a new connection point for the -pick signal. This is analogous to my use of HPS_I2C1_SDAT on LTC pin 9 for the touch pad interrupt signal. Both of those are routed to the GPIO1 bank of signals on the hard processor system where Linux and my applications run. I will already have addressability to that bank of signals because of the touch pad interrupt, thus we only need to add a bit in the mask to check this signal along with the other one. 


I took the program that validated my use of the LTC-9 pin, modified it to also look at LTC-11 and report the state of both. When I ran the test program I did see the state toggle on and off as I either wired LTC-11 to 3.3V or to ground. This completes all the functionality tests I intended, so that I can move on to larger scale testing. 

The next verifications I want to accomplish relate to the LCD screen and touch pad. First writing some text to the screen so that I can be sure I understand the addressing and the library calls involved. Second drawing a button to again understand the library calls and addressing. Third to test the touchpad results returned to distinguish between touches on the up button, the down button and the select button. Fourth, to display a bitmap on the screen of a 2315 cartridge as this will be displayed while the drive is turned on with a selected virtual cartridge. 

Verifying key functionality with small focused test programs, part 4


I have connected the signal -pick that comes from the IBM 1130 disk drive to GPIO8 on connector GPIO0. This is accessible from the FPGA logic where I use it to control whether we are emulating the disk drive or talking to the user interface code in the HPS side. Additionally, however, the HPS side needs to see this to control the user interface properly.

When the drive is switched off, the user interface presents a list of virtual cartridge images on the LCD screen, with buttons to scroll up and down when there are more than 40 image files installed. At the bottom is a Select button to allow the operator to select which cartridge is going to be virtually installed into the physical disk drive of the computer. 

The selection of an image causes its contents to be downloaded into the FPGA side in preparation for access by software running on the IBM 1130. The operator would then switch on the disk drive, which contains a dummy physical cartridge to spin up and provide appropriate signals to the disk controller and my FPGA logic. 

When the disk reaches speed, the drive controller sends a -pick signal, meaning it asks the drive to lower the heads down onto the drive. A microswitch in the drive informs the disk controller that the heads are indeed flying on the surface, which results in the drive going ready. My product replaces the microswitch with a signal from my FPGA logic to tell the controller the heads are down and ready. 

In order for me to send that ready signal to the controller, there must be a cartridge file image loaded into the FPGA (by the prior action of the operator pushing the Select button). Only when the -pick signal is on and an image is downloaded will I emit the signal to make the drive ready. Our challenge is that the GPIO8 pin on the FPGA side is not normally visible to code running on the HPS side.

Confusingly, Terasic names the two 40 pin connectors on the board GPIO0 and GPIO1, but these are connected only to FPGA logic and are unrelated to the GPIO1 signal bank that exists on the Cyclone V chip HPS side. There are various means of routing signals from the FPGA GPIO to the HPS GPIO, but it is convoluted. In this case, we are routing the FPGA pin GPIO8 on GPIO0 connector to the signal spim0_ss_in_n which is routed over the bridge from the HPS side to the FPGA side.

A designer can export control of the SPI master 0 link connections to the FPGA logic, which delivers signals for the clock, MOSI, MISO, four slave select lines and the master contention input spim0_ss_in_n. When that contention signal is at logic level 1, the SPI link will operate normally. However when that signal is dropped to logic 0, it blocks the SPI hardware from driving clocks or data bits. This is used so that multiple masters can share wiring to slave interfaces, with only one permitted to actively manipulate the wire signals at any instant. 

The HPS side does not provide access to the master contention signal spim0_ss_in_n but I believe I can see that state of this signal in the SPI interrupt status register. It appears that the signal is reflected in bit 5 of the ISR register, which I can access from Linux on the HPS side. The unknown was whether that state is only shown when code attempts to write on the SPI link while the signal (actually spim0_ss_in_n is the same as -pick) is low, blocking use.  

My test will interrogate that bit of the ISR register with the pick line at both 3.3V and then 0V to block the link. It then sends a word to the SPI while we are blocking it, again reflecting the state of the ISR bit. From that I can tell if this method to detect -pick will work. 

After a few self inflicted wounds in my test program, I was able to run this and discover to my dismay that the presence or absence of the -pick signal has no impact at all on the status or interrupt status registers. I dumped all the fields and verified that I had configured and enabled the SPI master. 

I will need to find a different way to pass this signal to the HPS side, verify it with a test, and then update my wiring diagram and documentation. I am thinking that I can use another of the LTC pins just as I used to pass along the touch pad interrupt signal. 


This was another self inflicted wound, which was rapidly fixed after I spotted the issue. The drive_ram signal switches on and off exactly as it should. 


I was attempting to issue a command automatically on bootup rather than through a terminal, just to save some time whenever I started up my Linux in the VMWare virtual machine. Unfortunately, I didn't realize that it would hang up the boot process rendering it impossible to do any work on the machine.

I downloaded an ISO image of Ubuntu, mounted it as the CD Rom 'contents' for the virtual machine and then brought it up. First I had to jump into the virtual BIOS of the virtual machine, via F2 key, to change the boot order to make the CD drive first. I then booted up the ISO image and started it in the "Try out Linux without Install" mode.

I could then mount my hard disk into the running Linux, navigate to where I installed the bad script and remove it. Once that was done, I rebooted into the BIOS, restored the hard drive as the primary boot source and then booted up my Ubuntu system. I was back in operation. First thing I did was export all my project files out of Linux just in case something like this happens again. 

Thursday, May 25, 2023

Verifying key functionality with small focused test programs, part 3


In operation, the programs running under Linux spin off a process that watches the HPS_USER_KEY signal, which is my power good/fail indication. When that signal goes to logic high we have lost AC power and are running off our battery. This process will issue a command to a shell (shutdown -h now) which commands Linux to do an orderly shutdown. 

I may add a bit more delay to allow the user interface to command an unload of any data that was written or updated from the IBM 1130, which would also protect the integrity of the virtual 2315 cartridges, but initially I am only ensuring that the SD Card is not in a corrupt state. This implies that the cartridge image being used on the 1130 would be the contents of the file when we first selected it for operation with any changes lost if there is an abrupt power down. 

If the operator has switched off the disk drive first, the  signal will tell us to request an unload to update our file on the SD Card so that nothing is lost; this is an issue only if power unexpectedly drops without the operator having first spun down the disk drive. 

My test program is very simply, it establishes accessibility to the HPS_USER_KEY signal in a process we spun off. We start without touching the pushbutton to simulate good power state. The test code indicates that it sees this. When we press the pushbutton, the code should warn us that power has dropped and then issue the shutdown. We know this works if we see Linux shutdown if and only if we push the pushbutton. 

Indeed, the system immediately shuts down when the button is pressed. In the actual implementation there will be the short delay to let everything wrap up, but this is tested and the method proven to work. 


My communications over the bridge from the program executing under Linux in the Hard Processor System side to the logic in the Field Programmable Gate Array side seems to work well, with status being read and commands executed with only one exception. The command that should turn the drive_ram signal back off is not being processed. I can start an unload and turn on drive_ram properly.

I changed that logic to return a special status that would at least provide that my logic did get the command, but I only get the normal 0000 status back. Something is awry, more digging will be done. 

Wednesday, May 24, 2023

Verifying key functionality with small focused test programs, part 2


I have wired the interrupt pin of the LCD + Touch module, which hosts the user interface of my product, to the LTC connector, pin 14. This should be routed to the GPIO1 bank of HPS I/O signals, at signal GPIO40.

Looking at signals on the GPIO1 bank is easy - provide addressability to a specific memory location that is mapped to this bank of signals and look at the bit associated with the signal. My code shows the bit value as I connect LTC pin 14 to 3.3V and to ground, ensuring that my code can see the interrupt when the user touches the screen.

I was previously unable to test this because the default logic loaded on the SD Card rerouted this signal to make it inaccessible from Linux. Now that I have set up my own logic with Linux running, I could test again. 

The initial results showed no change. I then checked the state of the pin I/O direction and forced it to be an input, but that was no better. I got suspicious and began to search through all the docs including the schematics, where I found that this pin is pulled up with a resistor and grounded as an output to switch the LTC connector between I2C and SPI signals. It is not a general I/O, just an output, I believe as the device drivers must be forcing this to a constant value such that I can't toggle the signal. 

Pullup on the HPS_LTC_GPIO pin

I had to pick a new pin where I could route that signal to detect that the touch pad interrupt was being generated because of a user interaction. I chose LTC connector pin 9, which was HPS_I2C1_SDAT connected to pin A21 and visible on GPIO51. When I ran the tests, I was able to see this pin both on and off as I moved a jumper around. Success!


I have set up two of the bridges between the FPGA and HPS sides in order to communicate between the two. One bridge is used to send simple commands, such as switch the FPGA logic to drive emulation mode, and to return status of the commanded operations to my code running under Linux. The other bridge transfers four words at a time when loading or unloading a virtual disk cartridge image to the FPGA. 

This test program establishes addressability and then turns the drive emulation mode on and off, which is verified both by the status words being returned and by an LED which illuminates on the board whenever drive emulation is on. If one bridge works, I would expect the other to work as well. 

I did see the drive_ram signal activate when I issued the command - the assigned LED lit -- and the status coming back from my FPGA logic was normal. I however did not see the lamp go out when I issued the command to turn off drive_ram which I will investigate further. 

I did modify the test program to end by sending an Unload command to the FPGA which would start it looping reading data from the RAM buffer we set aside and making it available for reading from the Linux programs which would put the changed contents away on to the virtual cartridge file on the SD Card. 

I saw the drive_ram light go off and the Unload function LED illuminate. When I requested status over the bridge from the FPGA I received the correct value to indicate that a load/unload was in progress. I had made a temporary change to the FPGA logic which reset the command as soon as a status was read - this turned off the unload operation which is not what we want to happen, thus I will fix this. 

I rate this a success as I see correct operation of my logic to transfer commands and status between the FPGA and the Hard Processor System (HPS) sides of the chip, which is essential for my design to work properly. 

Tuesday, May 23, 2023

I have my Linux and FPGA logic environment running on the DE10-Nano board


I was able to take the distribution SD Card image for "console", which did not work as it had several errors such as incorrect file names in the boot script u-boot.scr. I found them and corrected things such that it loads my FPGA configuration and then boots Linux successfully. 

Once I had the system mounting the FAT file system at startup to give access to the test programs I installed, we appear ready to resume testing. 

Verifying key functionality with small focused test programs, part 1


Before I launch into full scale tests of the operation of the Virtual 2315 Cartridge Facility I have identified certain signals that must be properly received by my software in order to achieve the behavior we designed into the product. 

I set up small programs that minimally test these elements, allowing me to verify that I understand things correctly and have everything properly configured so that I can detect the signals as I expect. These were generated on my laptop and moved onto the SD Card of the Hard Processor System (HPS) on the board where Linux will run. I can log into the Linux system by a serial connection and execute the test programs to check off each test. 


The power input monitoring signal is driven to ground when the supply from the IBM 1130 is active, but when power drops or the CPU itself drops, my product will be powered by a 12V battery to allow for a few minutes to properly execute a shutdown of the Linux image running on the board. This dramatically reduces the risk that the file system will be corrupted if there are writes on the fly when power drops. 

I tack a wire from my power monitoring wire to the HPS_USER_KEY pushbutton on the DE10-Nano board. This causes the pushbutton to appear depressed when my wire is pulled down to ground (good power) and it reverts to unpressed state if power has failed or is not present. 

This program allows me to test by simply pressing and releasing the pushbutton, as it is very unlikely that my tacked on wire will fail to operate properly. I have reviewed the schematic for the button and its traces on the board to ensure that I am indeed connected to the proper contact of the button. The action of the button is to connect my chosen contact to the other contact which is tied to ground.

My test worked properly, assuring me that my understanding of how to check signal values from the memory mapped areas is solid. This signal was available even with the provided Linux, system on chip design and FPGA logic for the board. Until I can load my own FPGA logic, the remaining signals pass through my logic or are rerouted in the default logic shipped with the board such that I can't access them. 


The startup process for the board is:

  1. Hardware functions execute the preloader
  2. Preloader will load the U-Boot program
  3. U-Boot takes actions including loading the FPGA logic into the hardware
  4. U-Boot transfers control to the Linux kernel
  5. Linux kernel and startup routines bring up the system to the point a user can log in

The U-Boot code is writing a fixed file name over into the FPGA but also invoking a program to configure the HDMI video link over in the FPGA to give a graphical interface through a monitor. The logic in the FPGA that handles the HDMI connection and video operations is intellectual property which is only available on the existing SD Card images, not to move into my own FPGA design. Thus, I can't use the HDMI link to support a graphical Linux desktop when my FPGA logic is loaded.

Some documentation from Terasic, Intel and on RocketBoard.org suggests that if the FPGA configuration file is not present, the Linux system will boot up without loading the FPGA. This would have allowed me to install my logic separately into the FPGA and then let Linux boot up. 


The existing SD Card images provided with the DE10-Nano load their own FPGA logic and configure signals between the FPGA and Hard Processor System (HPS) side where Linux will run. The existing code will NOT come up into Linux with my own FPGA configuration. It appears the documentation is out of date or was incorrect. 

The Linux kernel is apparently trying to communicate the the FPGA side HDMI logic very early in its startup, since it freezes if I replace the default file on the SD Card with my own FPGA logic. If I remove the FPGA file entirely, the U-Boot loader won't even attempt to start the Linux kernel. 


I have wired the interrupt pin of the LCD + Touch module, which hosts the user interface of my product, to the LTC connector, pin 14. This should be routed to the GPIO1 bank of HPS I/O signals, at signal GPIO40.

Looking at signals on the GPIO1 bank is easy - provide addressability to a specific memory location that is mapped to this bank of signals and look at the bit associated with the signal. My code shows the bit value as I connect LTC pin 14 to 3.3V and to ground, ensuring that my code can see the interrupt when the user touches the screen.

The default logic on the SD Cards reroutes the signal from the LTC connector so that it is not connected to the GPIO1 bank. I have not means of viewing the signal state until I can get my own design into the FPGA which leaves this signal on GPIO1. 

Monday, May 22, 2023

Cross compiling working well now, on to testing on the DE10-Nano


The issue that caused the toolchain to generate soft floating point versions of the binary files was related to the makefile. I was using the text editor on the Ubuntu desktop image under VMware, altering the makefile and saving it, but the behavior of the make was not what I expected. I eventually entered a completely incorrect line that should have caused make to fail, but it didn't. 

I happened to open the makefile with vi rather than the Ubuntu text editor and found a back level version of the file without my saved changes. When I fixed this up in vi, the make successfully built the binaries in hard floating point format. No idea why I can't depend on the text editor but that is not a priority to understand. 


When I fired up my test program on the DE10-Nano board, it complained that the GLIBC version on the board's linux didn't match the version set up by my cross compile. I certainly could have invested time to update the libraries on the board, but that introduced risks and wasn't necessary.


I simply linked the binary with static libraries. Problem solved and I was able to actually begin testing my methods to check buttons and read other signals. 

Snags getting the FPGA image loaded and my cross compile producing wrong ARM architecture


I have set up the gcc cross compilation environment to create binary files to run on ARM processors under Linux. On my windows laptop, I have Vmware installed and an Ubuntu Linux image set up. In that Linux environment I run the various Quartus tools and the cross compilation tasks.

The Gnu cross compile environment was installed to support the ARM instruction set, versions of the standard library modules that are generated for the ARM processors and all the appropriate parts to run under Linux. My makefile specifies the cross compile location automatically invoking the gcc and ld programs for the target environment. 


ARM has evolved over the years from its original Acorn and there are variants that do not have floating point instructions implemented. For those, a software environment will be invoked to simulate the floating point operations. ARM uses the terms soft and hard to delineate processors that use the software simulation assist from those that have the floating point instructions in silicon. 

The cross compile environment obviously varies for these two variants. The makefile points at the relevant files, in the case of Ubuntu those are at /usr/gcc-arm-linux-gnueabi for soft and /usr/gcc-arm-linux-gnueabihf for the hard version. My makefile points there which should cause the gcc and ld to be executed from /usr/gcc-arm-linux-gnueabihf/bin in order to produce the correct outputs. 


I issue the make command and produce binary files as output but when I interrogate the format using the readelf command, it identifies it as a soft floating point format, not the hard format I intend. This causes the binary to be rejected when I try to execute it on the Linux on my DE10-Nano board because that is a hard floating point system. 

I suspect there is some path variable or other issue that is confounding the toolchain because it is not producing the intended flavor of ARM binary. That is a task to address later today.


As part of the startup of the Linux image on the SD Card on my DE10-Nano board, it copies a file de10-nano.rbf into the FPGA to configure it with the logic to support connections such as the HDMI buffer running in FPGA for the Linux desktop to display on a monitor. I am using only a USB serial port connection in text mode, although there are alternatives using GUI I could activate over ethernet. Since I still have not set up a wifi to ethernet adapter to connect the board to my home network, I am restricted to USB UART connections. 

The straightforward method I attempted was to replace the current de10-nano.rbf file with my FPGA configuration file but under the same name. When my design was generated and compiled by Quartus, it created a file with a .sof suffix. A tool within Quartus converts this to a raw binary file format, .rbf, which is the file that I renamed to de10-nano.rbf. I expected this to load the FPGA side with my logic and then continue to boot up Linux so that I could log in and run my tests. 

Sadly, Linux failed to come up. I tried both the graphical desktop version that came with the DE10-Nano board and a so called console only version. Both fail, although in different ways. 


It appears that I have to regenerate the Linux and boot environment specific to my logic design, which is going to require quite a bit of study and experimentation to get this right. There appear to be preboot loader, Uboot, device tree and Linux generation requirements. 


As an alternative, the configuration file for the FPGA can be loaded into flash on the board via the Quartus programming environment, after which I can set up the board slide switches to have it load the FPGA from the flash. I was assuming that Linux would boot up and as long as I renamed the FPGA configuration file that it would load (de10-nano.rbf) it would skip over loading FPGA and complete initialization. 

Sadly this went into a boot loop so the claims in Rocketboard.org that the script allows it to boot if the .rbf file is missing are out of date and incorrect. I am back to the long tedious process. Hopefully I can complete tests of functions that don't depend on my FPGA logic being installed, while I work on what I hope will not be a Sisyphean journey. 

Thursday, May 18, 2023

Setting up the Terasic DE10-Nano environment for testing and eventual attachment to IBM 1130


This board is based on an Intel Cyclone V System on a Chip that provides a beefy Field Programmable Gate Array (FPGA) coupled to a pair of ARM cores (Hard Processor System - HPS) that run Linux. It has several peripheral capabilities including 1GB of RAM, wired Ethernet, UART USB link, SD Card drive, HDMI link, and an OTG USB capability.

As shipped, Angstrom Linux is installed in the HPS side and the FPGA side is loaded with logic that among other things provides a frame buffer for attachment of a monitor to the HDMI link. The HDMI is attached to the FPGA side, thus needs that support to allow the desktop to be displayed when Linux is running, while the OTG USB connects to a mouse and keyboard to complete the user interface for Angstrom. 

The SD Card inserted in the board contains the Linux image as well as other files accessed from the HPS side. That include the FPGA logic which is copied by the boot time code in Linux over to the FPGA. I intend to also host all the virtual disk cartridge files, each 1MB in size, on this SD Card. 

One can hook up the monitor, keyboard and mouse to immediately bring up and use the Linux system. If an ethernet cable is plugged into the board, it can join a network and communicate with other systems. Alternatively, a USB cable attached to the OTG connector provides a USB UART so that a serial terminal (or PC with a terminal program) can log onto Linux in text mode. 

The logic for the frame buffer is not documented nor shared, thus if someone wishes to set up the FPGA to accomplish any logical function, they lose the HDMI link and graphical interface with Linux. This leaves the serial text connection or connections such as SSH over ethernet if you load anything into the FPGA side. 


My Virtual 2315 Cartridge Facility project uses its own LCD touch screen for a user interface thus I don't care about the loss of the HDMI link to a PC monitor. However, I do need various signals connected to the general purpose IO pins that are attached to the FPGA side, but intended to be routed to code running on the HPS side. In addition, all the disk modeling and bit stream manipulation for the IBM 1130's internal disk drive is implemented in the FPGA.

I can move files to the SD Card by pulling it out of the DE10-Nano board, putting it in an external SD Card reader on my PC and manipulating the file system. This is a bit cumbersome, thus as an alternative I would like some means of directly moving files without shutting down, moving the card and then rebooting. Working on the best means. 


I plan to have several SD Cards each loaded with the virtual cartridge images, thus if anything goes wrong, the operator of this system can swap cards to restore operation. I will also use this for any variants I need during testing. For example, I might want to have network connectivity so that I can log in via SSH from my comfy chair while doing debugging. 


My first approach for enabling WiFi is to attach a USB WiFi Adapter to the OTG connector and then try to get the Linux image to enable it. While the USB interrogator function in Linux correctly identifies it as a Realtek 802.11ac adapter, it is not coming up as a wireless LAN for networking purposes. I have to dig into what is necessary to get the driver, assuming one exists for Linux, plus the correct network configuration to have this activate to connect to my home network. 


When I load my own FPGA image onto the SD Card and boot, the desktop oriented Linux is confused and emits error messages. Hoping to establish a cleaner environment, I downloaded what Terasic purports to be a Linux Console only Linux image from their website. This won't complete booting and drops into the boot monitor prompt, meaning I have some debugging to accomplish before I can get this to come up as I intend - Linux with only the UART serial means of logging in. 

Friday, May 12, 2023

Working on user interface code and dealing with non portable example code


The touchscreen LCD module I purchased for use with the Virtual 2315 Cartridge project came with example code which is saving quite a bit of time in creating my user interface. The module was intended for use with a Pi Pico board, having a socket to fit that processor board. 

Unfortunately the example code also reflected the RP2040 microcontroller and its software development kit. The way that peripheral connections are managed and Serial Peripheral Interface (SPI) links are controlled is quite a bit different from the methods used with Arduino or in my case the ARM cores in the Intel Cyclone V system on a chip. 

I had to make many changes to adapt the code to the Terasic DE10-Nano using the Cyclone V but it seemed to be reasonably straightforward up until I began to use the touch interface to detect when various screen 'buttons' where being pushed by the operator. 


Doing a make to cross compile the code triggered quite a few errors related to an undefined function sqrt which is clearly meant to be the math function calculating a square root. I wasted time believing that my cross compiling environment was not properly pointing at the include files and library files wherein it would find sqrt, before I looked closer at the code and spotted my problem.

This code calls the sqrt function with inputs and outputs that are unsigned integers, whereas the standard function in C only deals with floating point data types. Thus, having math.h included and the math library linked was of no use for the ARM Linux environment. It appears that Pi Pico does support this and the code is thus very unportable. 


I am in the midst of understanding the intent behind all the math done in the touchscreen example code so that I can convert it appropriately. It helps quite a bit that my design for the user interface has only three touchable soft buttons, which are largeish and well separated. This reduces the need for careful calculation to associate a touch interrupt with the spot on the screen. I only need to discriminate between three cases - Up, Down, and Select buttons.