Sometime back in 2018, I tried out a fresh install of Ubuntu MATE 18.04 on one of my computers and noticed a strange problem when I attempted to install Google Chrome. I clicked the little Firefox icon in the top panel:

Then I downloaded the latest Chrome .deb from Google and opened it up from inside of Firefox:

At this point, GDebi popped up giving me the option to install it. Everything seemed totally normal so far.

Read the rest of this entry

Way back in part 2 of this series, I first got my Chumby 8 booting into a newer Linux kernel. (Here are links to parts 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, and 11 if you want to read the rest of the saga). At that point early on in the project, I had to get the UART driver working. I didn’t spend much time talking about the UART in that post, but it actually gave me a small challenge that I recently had to revisit. I thought it would be fun to tell the full story of the UART struggles I ran into.

When I was first figuring out how to configure my new kernel, I noticed that the pxa168.dtsi file included in the mainline kernel already had the UARTs added. They each had two compatible strings, in order of priority: mrvl,mmp-uart and intel,xscale-uart. This makes sense because Intel’s XScale architecture was used for many things including the PXA series. Then the PXA series was sold to Marvell in 2006, who later designed the PXA16x processor used in the Chumby 8.

Searching through the kernel sources, there were actually three drivers that reference the mrvl,mmp-uart compatible string: 8250_pxa, 8250_of, and the deprecated pxa driver. I originally tried out 8250_pxa, but I ran into a problem with it. During large transmits, for example when typing “dmesg” after the kernel booted, it would drop a ton of characters. Here’s a small excerpt of a modern recreation of the issue in a newer kernel:

Read the rest of this entry

This weekend I tinkered with my ancient Raspberry Pi. It’s the original Model B from 2012 that only has 256 MB of RAM. I bought it in July of 2012 for $35, and then a few months later they started being manufactured with 512 MB instead. I wish I had waited a little longer to buy mine!

I’ve played around with it a little bit off and on over the years, like when I was working on some improvements for RPiPlay. But for the most part it just sits around doing nothing. I was inspired when I heard about someone who was recently having trouble playing video on their Model B+ 1.2.

They reported that while attempting to play a 1080p H.264 video file in VLC on the Pi, it would only play at about 3 frames per second, despite lots of Google searching and OS reinstalls. I had dealt a little bit with H.264 when I was playing with RPiPlay, so I was kind of familiar with the situation. I went ahead and imaged an SD card with the latest Raspberry Pi OS compatible with this model. According to the Raspberry Pi website, as of this writing the latest version is Raspberry Pi OS 32-bit from March 15th, 2024 with Debian bookworm and Linux kernel 6.6. I opted for the “with desktop” version so it would boot into a full-fledged OS so I could try VLC and other options.

Read the rest of this entry

As my Chumby 8 kernel upgrade project neared the finish line (read parts 1, 2, 3, 4, 5, 6, 7, 8, 9, and 10 first if you want), I noticed something subtly annoying. The built-in SD/CF card reader was allocating its own dummy block device (/dev/sda) even if no cards were inserted.

scsi 0:0:0:0: Direct-Access Multi Flash Reader 1.00 PQ: 0 ANSI: 0
sd 0:0:0:0: [sda] Media removed, stopped polling
sd 0:0:0:0: [sda] Attached SCSI removable disk

# ls /sys/class/block/
mmcblk0 mmcblk0p1 mmcblk0p2 mmcblk0p3 sda

This may seem nitpicky, but I really didn’t want that empty sda device hanging around. Apparently neither did the original Chumby team, because the old 2.6.28 kernel had a workaround to avoid it. Let’s look at the relevant portion of the schematics. There are two sockets, and the SD/MMC/MS/xD socket has a bunch of pins for different card types, so the card reader takes up two whole pages. Let’s focus on just the SD/MMC pins. You can imagine that the CF/MS/xD sections look very similar:

Read the rest of this entry

What follows is the story of how I fixed not one, but two, different flawed Altera USB Blaster clone devices that never worked correctly after I bought them.

I recently built a few Time Sleuths for HDMI input lag testing. Time Sleuth is a neat little open-source project that allows you to measure the time it takes for your TV or monitor to display an image. The way it works is an Altera/Intel MAX 10 FPGA creates a video signal that is mostly a black screen with some blinking white boxes. It feeds the image off to a TI TFP410 DVI transmitter, and also looks for a pulse on a photodetector. It measures the difference in time between when the white box blinked on and the photodetector saw it, and displays it as a number on its generated video signal with some min/max/average stats. Pretty cool! If you’re not into soldering, you can also buy them fully assembled.

Read the rest of this entry

I’m going to start this post off with the obligatory list of links to the previous parts in the series if you’re new here and are interested in seeing the full story: 1, 2, 3, 4, 5, 6, 7, 8, and 9. This is the tale of how I upgraded my Chumby 8 to run a modern Linux kernel.

I only had some minor things on my list to figure out before I could call my kernel upgrade good enough to be finished. The most important remaining thing was the real-time clock, or RTC. I noticed that whenever I rebooted the Chumby, it always started out with the date set to the Unix epoch in 1970:

# date
Thu Jan 1 00:00:12 UTC 1970

I had observed earlier that the default pxa168.dtsi file in the kernel had an RTC already added, but it was disabled:

rtc: rtc@d4010000 {
compatible = "mrvl,mmp-rtc";
reg = <0xd4010000 0x1000>;
interrupts = <5>, <6>;
interrupt-names = "rtc 1Hz", "rtc alarm";
clocks = <&soc_clocks PXA168_CLK_RTC>;
resets = <&soc_clocks PXA168_CLK_RTC>;
status = "disabled";
};

Would it really be this simple? Did I just need to enable the RTC in my device tree file, make sure the kernel driver was enabled, and then be done with it? I had already experienced similar success with other PXA168 peripherals. So I tried it out.

Read the rest of this entry

If you’re new to this series, I’ve been documenting the process I went through upgrading my old PXA166-based Chumby 8’s 2.6.28 Linux kernel to a modern 6.x version. Here are links to parts 1, 2, 3, 4, 5, 6, 7, and 8. At this point in the project, all of the main hardware peripherals were working great. I noticed something odd when running top though. The CPU usage was always really high, and it wasn’t obvious why.

Mem: 47888K used, 55968K free, 168K shrd, 3116K buff, 27480K cached
CPU: 100% usr 0% sys 0% nic 0% idle 0% io 0% irq 0% sirq
Load average: 0.00 0.00 0.00 2/51 269
PID PPID USER STAT VSZ %VSZ %CPU COMMAND
267 200 root R 2936 3% 100% top
100 1 root S 12240 12% 0% /sbin/udevd -d
1 0 root S 2936 3% 0% init
200 1 root S 2936 3% 0% -sh
65 1 root S 2936 3% 0% /sbin/syslogd -n
71 1 root S 2936 3% 0% /sbin/klogd -n
34 2 root SW 0 0% 0% [irq/56-mmc0]
10 2 root IW 0 0% 0% [kworker/0:1-eve]
11 2 root IW 0 0% 0% [kworker/u2:0-ev]
41 2 root IW< 0 0% 0% [kworker/0:2H-kb]
8 2 root IW 0 0% 0% [kworker/0:0-lib]
22 2 root IW< 0 0% 0% [kworker/0:1H-mm]
32 2 root SW 0 0% 0% [irq/55-mmc1]
14 2 root IW 0 0% 0% [rcu_preempt]
17 2 root IW 0 0% 0% [kworker/u2:1-ev]
15 2 root SW 0 0% 0% [kdevtmpfs]
27 2 root IW 0 0% 0% [kworker/0:2-pm]
2 0 root SW 0 0% 0% [kthreadd]
13 2 root SW 0 0% 0% [ksoftirqd/0]
3 2 root SW 0 0% 0% [pool_workqueue_]

Read the rest of this entry

After getting many of the PXA16x peripherals working in modern Linux kernels during my Chumby 8 kernel upgrade saga (here are links to parts 1, 2, 3, 4, 5, 6, and 7), I really felt like I was starting to reach the finish line. The display was working well enough to play low-resolution videos, I had basic 2D acceleration up and running, the touchscreen was operational, and Wi-Fi worked flawlessly. Audio was the only major component left to tackle. The Chumby 8 has built-in speakers, a headphone jack, and a microphone.

The Linux sound subsystem is something I had exactly zero experience with prior to this project, so it felt very intimidating. It took me a while to get familiar with it. The relevant project is Advanced Linux Sound Architecture (ALSA) and in particular, the ALSA System on Chip (ASoC) layer is where most of my work would be for this project.

Before digging in too deep, I needed to look at the Chumby 8 schematics and figure out what I would be dealing with. With no prior audio experience to lean on, I wasn’t sure what to expect. Let’s take a look at the relevant section of the schematic:

Read the rest of this entry

After getting the PWM backlight working in my last post (here are links to parts 1, 2, 3, 4, 5, and 6), there was only one piece remaining for having a fully functional display in my Chumby 8: the touchscreen controller. The display output worked perfectly fine but I couldn’t detect presses on it.

The Chumby 8 and Insignia Infocast 8 have a 4-wire resistive touchscreen:

These aren’t so common anymore — it seems like almost everything is capacitive touch nowadays. I wasn’t familiar with the theory of operation behind resistive touchscreens until I wrote this post. Basically there are two transparent resistive layers. One layer goes left and right and the other goes up and down. When you press the touchscreen they connect together. You can calculate the X and Y positions where the layers meet by driving a voltage across one layer and then measuring the voltage of the other layer. Here’s a nice document that does a great job of explaining it in detail.

Read the rest of this entry

I recently ran into an interesting warning on newer versions of ARM GCC, including the latest (as of this writing) Arm GNU Toolchain 12.3.Rel1. In particular I’m dealing with arm-none-linux-gnueabihf-g++. Here’s a very simple example program that demonstrates the warning:

#include <vector>
#include <iostream>

int main(int argc, char *argv[])
{
	std::vector<double> test;
	test.push_back(50.0);

	std::cout << test[0] << std::endl;

	return 0;
}

Read the rest of this entry