NetBSD on R-pi 1 and 2

Raspbian is starting to become too heavy... some weird system-based stuff happens, then there is a cloud-thing. We do not need any of that on the old 512MB devices which mostly sit in some dark corner reporting on and controlling something.

Installing NetBSD on the r-pi and initial observations

The installation job is familiar: download an image to put on an SD-card, put the card into its place, and power up.

Initial installation on console has root with blank password. We must set one

Add users to the users group with specified uids:

useradd -u 201 -G wheel -g users hware

There is also the usermod command ther, to change things.

Set hostname etc. in /etc/rc.conf

users should be in the wheel group so they can use su to change to root as needed.

It is notable that the manual pages seem very comprehensive, compared to the ones on Linux. There will be references to them in the following, since they are really helpful with discovering how the system works.

C

The C compiler reports itself to be cc (nb3 20231008) 10.5.0 It is useful to see what other things it complains about compared to gcc and clang. clang didn't like some old K&R-style definitions but this cc is unhappy about ctype function looking at character arguments (not integer arguments).

Also, there is no qsort_r function defined so a workaround had to be made for that.

struct timeval wasn't defined where expected, it is however available from s<sys/time.h>

Compiling the usual utilities show there is no /usr/local so we start out making:

/usr/local/src
/usr/local/bin
/usr/local/lib
/usr/local/include

Then the ldconfig has to be changed. In file ld.so.conf, had to add /usr/local/lib there.

Now all the usual utilities work.

i2c

There are three i2c busses enabled. Their devices are /dev/iic0, /dev/iic1, and /dev/iic2.

The main one that has SDA on pin P3, and SCL on pin P5 is /dev/iic2, while the others may be less obvious. One would be the on on P27/P28, and one is for the HDMI.

The tool i2cscan that exists is less than useful, it seems to report something on every address on every bus, from 0x09 to 0x77.

Programming notes:

The communication is through ioctl(2) calls to the open(2) iic device, with the command I2C_IOCTL_EXEC where a struct i2c_ioctl_exec is passed with information about what to do. These constants and types are defined in /dev/i2c/i2c_io.h As usual with these things, we need to include the fcntl.h, unistd.h and sys/ioctl.h. All the details are in man 4 iic.

The operations can be write or read, with or without terminating with a stop conditions. SMBus equivalent actions typically use the I2C_OP_READ_WITH_STOP and I2C_OP_WRITE_WITH_STOP stop condition. Which ones are applicable will depend on the actual device in use. For example, READ_BLOCK or repeated reads without stop would be typical for multibyte reads from EEPROMs and other devices that have an automatically incrementing read address register.

gpio

While the i2c comes ready configured for use out of the box, accessing the other gpio lines is a little more work. While the actual IO is handled through the ioctl calls as per man 4 gpio, there is some configuration needed prior to that in order to make this available.

The default is no gpios made available. Obviously this isn't very interesting, so how to turn things on?

First, the main breaker has to be turned on in /etc/rc.conf through the statement

gpio=YES

Then, there is a file /etc/gpio.conf where each gpio line to be used after startup is identified, possibly given a name, and the configuration state, such as input, output, or one of the alternate functions, which will have to be found through hardware documentation.

man gpio.conf has all the details.

For a project using the Pi 2 with the 40-pin gpio header, I have used the following in this file. The gpios all sit on device gpio0, and the number is the traditional GPIO numbers. Some of these are input, others are output, and which is which will depend on what is to be connected there. The power pins and reserved pins are listed as comments. The pins used for i2c do not need any configuration info here.

Some of the ones set here as alt0 are used for SPI, more on that in further down.

They have been assigned names based on the physical pin number, but any other reasonable name will do.

# Blank lines and lines beginning with # are ignored
# 3.3 V P_1
# gpio0 2 set alt0 P_3
# gpio0 3 set alt0 P_5
gpio0 4 set in P_7
# GND P_9
gpio0 17 set in P_11
gpio0 27 set in P_13
gpio0 22 set in P_15
# 3.3 V P_17
gpio0 10 set alt0 P_19_MOSI
gpio0 9 set alt0 P_21_MISO
gpio0 11 set alt0 P_23_SCLK
# GND P_25
# gpio0 0 set in P_27_ID_SDA
gpio0 5 set in P_29
gpio0 6 set in P_31
gpio0 13 set in P_33
gpio0 19 set in P_35
gpio0 26 set in P_37
# GND P_39

# 5 V P_2
# 5 V P_4
# GND P_6
#  gpio0 14 set in P_8_TxD
#  gpio0 15 set in P_10_RxD
gpio0 18 set in P_12
# GND P_14
gpio0 23 set in P_16
gpio0 24 set in P_18
# GND P_20
gpio0 25 set in P_22
gpio0 8 set alt0 P_24_CE0
gpio0 7 set alt0 P_26_CE1
# gpio0 1 set in P_28_ID_SCL
# GND P_30
gpio0 12 set in P_32
# GND P_34
gpio0 16 set in P_36
gpio0 20 set out P_38
gpio0 21 set out P_40

With this in place, then gpioctl gpio0 list will show the ones that are enabled and with the assigned names.

4: P_7
5: P_29
6: P_31
7: P_26_CE1
8: P_24_CE0
9: P_21_MISO
10: P_19_MOSI
11: P_23_SCLK
12: P_32
13: P_33
16: P_36
17: P_11
18: P_12
19: P_35
20: P_38
21: P_40
22: P_15
23: P_16
24: P_18
25: P_22
26: P_37
27: P_13

Programming uses ioctl(2) calls on the open(2) /dev/gpio0 device. Thus we have to include unistd.h, fcntl.h, errno.h, sys/types.h, sys/gpio.h, and sys/ioctl.h, GPIOWRITE and GPIOREAD defined in sys/gpio.h are the main ones that are used, for reading and writing.

Unfortunately, there is no event capturing or interrupting ability made. The documentations has that shown as a bug. So some kind of wait loop reading a gpio line repeatedly, or some kind of secondary hardware that can catch and hold events, has to be added for this. It was necessary to do so for the rain gauge, to capture the 1/10 mm pulses coming from it.

SPI

SPI is also not enabled right away. It can be enabled for use, and it works well once turned on. Like the gpio and i2c it uses ioctl calls for its operation.

Enabling the spi0 bus:

Look in /boot/dtb for the relevant dtb file. For the Pi2 this is bcm2836-rpi-2-b.dtb Make a backup copy of this file.

Convert this to the editable .dts file:

dtc -I dtb -O dts bcm2836-rpi-2-b.dtb -o bcm2836-rpi-2-b.dts

Look for the entry for spi@7e204000

Change the status there from "disabled" to "okay"

convert back to dtb:

dtc -I dts -O dtb bcm2836-rpi-2-b.dts -o bcm2836-rpi-2-b.dtb

Set the alternate function 0 for gpios 7 thru 11 in /etc/gpio.conf:

gpio0 7 set alt0 P_26_CE1
gpio0 8 set alt0 P_24_CE0
gpio0 9 set alt0 P_21_MISO
gpio0 10 set alt0 P_19_MOSI
gpio0 11 set alt0 P_23_SCLK

The names P_26_CE1 etc. are for convenience and ease of discovery. there must also be a statement

gpio=YES

in /etc/rc.conf for configuring this, as is also required with the regular gpios.

Reboot. /dev/spi0 is now present and can be made opened with open(2) and do work using the ioctl(2) calls as per spi(4).

Programming notes:

As usual, we have to include the unistd.h, fcntl.h, and sys/ioctl.h, along with dev/spi/spi_io.h.

The code has to configure the relevant SPI device:

    struct spi_ioctl_configure sic;

    int sic.sic_addr;					0 for device driven by CE0 (P26), 1 for device driven by CE1 (P24)

    int sic.sic_speed;					SPI bus speed.  Set to 100000 or some such useful value. 
										DO NOT SET TO 0. If set to 0 the machine will hang, and 
										have to be power-cycled!

    int sic.sic_mode;					SPI mode, 0 to 3
										Mode 0: cpol=0 cpha=0 
										Data is shifted out on falling SCLK and when CE activates
										Data is shifted in on rising SCLK
										Mode 1: cpol=0 cpha=1 
										Data is shifted out on rising SCLK 
										Data is shifted in on falling SCLK
										Mode 2: cpol=1 cpha=0 
										Data is shifted out on rising SCLK and when CE activates
										Data is shifted in on falling SCLK
										Mode 3: cpol=1 cpha=1 
										Data is shifted out on falling SCLK
										Data is shifted in on rising SCLK

	s = ioctl(fd, SPI_IOCTL_CONFIGURE, &sic);

Having configured, we can read and/or write.

    struct spi_ioctl_transfer sit;

    int sit.sit_addr;					0 for device driven by CE0 (P26), 1 for device driven by CE1 (P24)

    const void *sit.sit_send;			Octets to be sent, NULL if nothing.
    size_t sit.sit_sendlen;				Number of octets to be sent. 0 if none.

    void *sit.sit_recv;					Space for Octets to be received
    size_t sit_recvlen;					Expected number of octets

	s = ioctl(fd, SPI_IOCTL_TRANSFER, &sit);

Testing was done using a max31855 thermocouple thermometer. This only needs the receive function, and reads 32 bits in 4 octets.

Other spi busses.

There may be a similar way to enable another spi device, spi1.

The spi@7e215080 entry in the dts file must be changed to "okay"

This bus has 3 device-select lines, and thus 3 addresses. The entries in /etc/gpio.conf will be something like:

gpio0 16 set alt4 P_36_CE2
gpio0 17 set alt4 P_11_CE1
gpio0 18 set alt4 P_12_CE0
gpio0 19 set alt4 P_35_MISO
gpio0 20 set alt4 P_38_MOSI
gpio0 21 set alt4 P_40_SCLK

Note the alternate function for these is alt4.

sic_addr and sit_addr can thus be 0, 1, or 2 for devices on this bus.

There is also mention of a third bus, spi2, but this is on gpios 40--45 which we don't have any access to.


Powered by Apache

Valid XHTML 1.0!