16 Jan 2023

Coordinated Holiday Lights - box 2

The second box that I put together features an Olimex iMX233-OlinuXino-MAXI for the SBC, connects to the network via an ethernet-over-power device, and uses a Digital Loggers "IoT Relay" device. The MAXI features the i.MX233 SoC which has a 32-bit, ARM9 arm926ej-s at its core. My intention is to use this device to run the lights on the bush in front of the house.

Parts:

When I was first thinking of this project (a couple years ago), I thought the "IoT Relay" from Digital Loggers would be a good device around-which to create my design. I was hoping it would keep me from having to do a lot of cutting and splicing of mains power cables. However, in order to get cables into and out of the box, cutting and splicing is unavoidable. So while these are neat devices, and I did end up using a couple of them (I had already bought them for this project), they're a little over-kill. Simple relays (as in box 1) would be more than adequate, and would save a bunch of space. Nevertheless, the IoT Relay has 4 NEMA 5-15P outlets: 3 of which are controlled by the control signal, 1 of which is "always on" (provided the device itself has power and is switched on). 2 of the 3 controlled outlets are "normally OFF" and the 3rd outlet is "normally ON". A removable screw terminal provides the signal by which to control the relay.

To supply power for the MAXI, I simply plugged the 12V 1A wall wart that came with the board into the IoT Relay's "Always ON" outlet.

The piggy-back NEMA 5-15P to C13 do-hicky was quite a lucky find! The IoT Relay has a C14 connector, and I needed a second 5-15P for the powerline adapter, so this device was able to solve both problems.

One small thing that tripped me up momentarily when working with the MAXI is that it doesn't have a manufacturer-assigned, static MAC address. I noticed this while setting up and testing my DHCP configuration, this board kept being assigned an IP address from the DHCP pool instead of the static IP I wanted it to have. Fortunately setting up a static, user-defined, locally-administered, unicast, MAC address isn't too difficult if it only needs to be set when Linux runs (if you need your bootloader to know/setup the MAC address, then other arrangements need to be made).

The iMX233-OlinuXino-MAXI is designed around the Freescale (now NXP) i.MX233 SoC. This SoC has an arm926ej-s at its core. The arm926ej-s was introduced in 2001; the i.MX233 SoC was brought to market in 2009. Despite its age, this SoC is still being produced, and Olimex is still building and selling boards around this device. Unfortunately, being an older device, its Linux kernel support isn't up to par. One of the issues is due to the fact it is so old, meaning it receives less active development. When it was introduced and support was added for it in the Linux kernel, the kernel had a completely different GPIO subsystem. In the intervening years that subsystem has been entirely re-written. All the newer, more popular, regularly-used SoCs all had their GPIO subsystems well integrated with the new subsystem. Older SoCs compile, but that's about it. As a result the kernel's GPIO information is rather lacking:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
root@imx233-olinuxino-maxi:~# gpioinfo 
gpiochip0 - 32 lines:
        line   0:      unnamed       unused   input  active-high 
        line   1:      unnamed       unused   input  active-high 
        line   2:      unnamed       unused   input  active-high 
        line   3:      unnamed       unused   input  active-high 
        line   4:      unnamed       unused   input  active-high 
        line   5:      unnamed       unused   input  active-high 
        line   6:      unnamed       unused   input  active-high 
        line   7:      unnamed       unused   input  active-high 
        line   8:      unnamed       unused   input  active-high 
        line   9:      unnamed       unused   input  active-high 
        line  10:      unnamed       unused   input  active-high 
        line  11:      unnamed       unused   input  active-high 
        line  12:      unnamed       unused   input  active-high 
        line  13:      unnamed       unused   input  active-high 
        line  14:      unnamed       unused   input  active-high 
        line  15:      unnamed       unused   input  active-high 
        line  16:      unnamed       unused   input  active-high 
        line  17:      unnamed "regulators:regulator@0" output active-high [used]
        line  18:      unnamed       unused   input  active-high 
        line  19:      unnamed       unused   input  active-high 
        line  20:      unnamed       unused   input  active-high 
        line  21:      unnamed       unused   input  active-high 
        line  22:      unnamed       unused   input  active-high 
        line  23:      unnamed       unused   input  active-high 
        line  24:      unnamed       unused   input  active-high 
        line  25:      unnamed       unused   input  active-high 
        line  26:      unnamed       unused   input  active-high 
        line  27:      unnamed       unused   input  active-high 
        line  28:      unnamed       unused   input  active-high 
        line  29:      unnamed       unused   input  active-high 
        line  30:      unnamed       unused   input  active-high 
        line  31:      unnamed       unused   input  active-high
gpiochip1 - 32 lines:
        line   0:      unnamed       unused   input  active-high 
        line   1:      unnamed       unused   input  active-high 
        line   2:      unnamed       unused   input  active-high 
        line   3:      unnamed       unused   input  active-high 
        line   4:      unnamed       unused   input  active-high 
        line   5:      unnamed       unused   input  active-high 
        line   6:      unnamed       unused   input  active-high 
        line   7:      unnamed       unused   input  active-high 
        line   8:      unnamed       unused   input  active-high 
        line   9:      unnamed       unused   input  active-high 
        line  10:      unnamed       unused   input  active-high 
        line  11:      unnamed       unused   input  active-high 
        line  12:      unnamed       unused   input  active-high 
        line  13:      unnamed       unused   input  active-high 
        line  14:      unnamed       unused   input  active-high 
        line  15:      unnamed       unused   input  active-high 
        line  16:      unnamed       unused   input  active-high 
        line  17:      unnamed       unused   input  active-high 
        line  18:      unnamed       unused   input  active-high 
        line  19:      unnamed       unused   input  active-high 
        line  20:      unnamed       unused   input  active-high 
        line  21:      unnamed       unused   input  active-high 
        line  22:      unnamed       unused   input  active-high 
        line  23:      unnamed       unused   input  active-high 
        line  24:      unnamed       unused   input  active-high 
        line  25:      unnamed       unused   input  active-high 
        line  26:      unnamed       unused  output  active-high 
        line  27:      unnamed       unused   input  active-high 
        line  28:      unnamed       unused   input  active-high 
        line  29:      unnamed       unused   input  active-high 
        line  30:      unnamed       unused   input  active-high 
        line  31:      unnamed       unused   input  active-high 
gpiochip2 - 32 lines:
        line   0:      unnamed       unused   input  active-high 
        line   1:      unnamed      "green"  output  active-high [used]
        line   2:      unnamed       unused   input  active-high 
        line   3:      unnamed       unused   input  active-high 
        line   4:      unnamed       unused   input  active-high 
        line   5:      unnamed       unused   input  active-high 
        line   6:      unnamed       unused   input  active-high 
        line   7:      unnamed       unused   input  active-high 
        line   8:      unnamed       unused   input  active-high 
        line   9:      unnamed       unused   input  active-high 
        line  10:      unnamed       unused   input  active-high 
        line  11:      unnamed       unused   input  active-high 
        line  12:      unnamed       unused   input  active-high 
        line  13:      unnamed       unused   input  active-high 
        line  14:      unnamed       unused   input  active-high 
        line  15:      unnamed       unused   input  active-high 
        line  16:      unnamed       unused   input  active-high 
        line  17:      unnamed       unused   input  active-high 
        line  18:      unnamed       unused   input  active-high 
        line  19:      unnamed       unused   input  active-high 
        line  20:      unnamed       unused   input  active-high 
        line  21:      unnamed       unused   input  active-high 
        line  22:      unnamed       unused   input  active-high 
        line  23:      unnamed       unused   input  active-high 
        line  24:      unnamed       unused   input  active-high 
        line  25:      unnamed       unused   input  active-high 
        line  26:      unnamed       unused   input  active-high 
        line  27:      unnamed       unused   input  active-high 
        line  28:      unnamed       unused   input  active-high 
        line  29:      unnamed       unused   input  active-high 
        line  30:      unnamed       unused   input  active-high 
        line  31:      unnamed       unused   input  active-high

Therefore, in order to figure out how its GPIOs connect to the SoC, we're going to have to do some digging into the board's schematics, then into the SoC's Reference Manual.

Thankfully, being open hardware, the schematics are publicly available (thank you Olimex!). The MAXI has a large, 40-pin, male connector on its side which is described in the schematic. Pretty much any GPIO line could be used, I decided to use the one labeled "PIN30".

Looking at the schematic:


We can see that PIN30 is connected to pin #28 of the board connector. We can also see that PIN30 connects to the SoC's pin 81, and the the SoC knows this pin as GPMI_CE1N.

[NOTE: There seems to be a little mistake in this schematic since it shows the SoC's pin 81 not connected to anything. Thankfully that's not the case, and we can associate the SoC pin with the connector pin by the common wire name: PIN30]

Now if we look at the SoC's Reference Manual and search for GPMI_CE1N we find (on page 37-28):


and we also find (on page 37-7):


Both of these confirm that the SoC pin known as GPMI_CE1N is found in GPIO bank 2, pin 27.

[NOTE: This SoC comes in 2 form factors: 128-pin QFP and 169-pin BGA. The schematics from Olimex show that they're using the MCIMX233CAG4C specifically. Page 41-1 of the Reference Manual shows that the CAG4C is the 128-pin LQFP (actually it shows that the CAG4B is the 128-pin LQFP, but searching on the Internet shows that the CAG4C is simply a later revision of the same device). When you're looking at the pin descriptions in the Reference Manual, make sure you're looking at the tables for the QFP specifically and not the BGA, otherwise you'll get the wrong GPIO bank/pin]


Performing the following simple test on the target board with everything wired up correctly proves we've found the right place:

1
root@imx233-olinuxino-maxi:~# gpioset gpiochip2 27=1

One thing that I did notice about this device compared to the other SBCs that I used for these boxes is that this SoC does run noticeably slower than the others. If I used systemd for the init system the device would run just fine for a while, but then become completely unresponsive for quite a while (perhaps 30 seconds?). Then it would run perfectly fine for many minutes, but then be unresponsive. When it was possible to type in commands again, running cat /proc/loadavg would show a lot of recent activity. Switching to sysvinit gives a system that doesn't have unresponsive gaps.

I had decided that I was going to install an ssh server on all these devices so I could interact with them "in the field" should I so desire. As part of any device's first boot with an ssh server installed, a bunch of security keys need to be generated. Without exaggeration, installing an ssh server on this device causes the first boot to take well over 5 minutes before a command line is reached as the device generates/calculates its ssh keys. Maybe using dropbear would be better? I didn't check. My guess is that dropbear would need to generate its own initial keys as well, so it would probably run just as poorly on first boot?

I suspect the real source of the problem is the the random number generator code in the kernel. Random numbers produce the best security keys, but generating randomness from deterministic devices is difficult. Over the years the Linux kernel has had several iterations of the random-generating subsystem as people find issues. Most modern SoCs now come with circuitry specifically designed to generate randomness in order to feed the pool of entropy that is used to generate secure keys (for example). This new code assumes such units exist, but in older hardware they either don't exist, or the kernel's drivers haven't been updated to support the new functionality. In any case, generating the randomness required to create cryptographically secure keys (by some definition of "secure") takes a long time.

Conceptually box2 could be described by the following Fritzing diagram:




Here's how the box looked partway through the build (I don't seem to have a pic of it when it was done):


Before installation:



After installation:


No comments:

Post a Comment