TERM=aaa60 Mk.2

More serial port shenanigans.

In our last episode, our intrepid hero lamented the lack of hardware flow control on the TTL-based something-like-a-serial-port that the Raspberry Pi provides. Well, in the comments someone pointed out that the Pi hardware actually does support flow control on the serial line, after you jump through some hoops to activate the "secondary function mode" on a couple of random pins. So I hooked that up.

But, unsurprisingly, it did not just magically work on the first try.

There are any number of things that could be going wrong here, so the first question I want to ask is probably, "when the Pi attempts to turn RTS on and off, does the light on my serial tester cable change state?"

So like, how do I do that? How do I toggle the RTS line through software?

Also, I'm not 100% sure I'm hooking up the right pins. Some sanity checking, please?

(Fun fact that I managed to go my entire life until today without realizing, which suddenly explains so many things: did you know that the RS232 DB25 spec has TX/RX on pins 2/3, but the RS232 DB9 spec swaps them to 3/2? And that is not for a null modem.)

So. The DB25 on the terminal is using pins 2 (TX), 3 (RX), 4 (RTS) and 20 (DTR). Pin 5 (CTS) is wired to ground.

This has made me realize that I don't actually know the difference between DTR and CTS. I thought they were synonyms, not different pins. Uhhhh...

So here's how I wired it up. TX/RX are swapped to null-modem it, as are RTS/DTR. Does this seem right?

2 RX2 TX14 TX
3 TX3 RX15 RX
4 RTS4 DTR  16 CTS
20 DTR  7 RTS17 RTS

Update: No, that was wrong, I got turned around: CTS is not wired to ground. However, there is a DTR with no corresponding DSR. So this is more sensible:

2 RX2 TX14 TX
3 TX3 RX15 RX
4 RTS8 CTS  16 CTS
5 CTS  7 RTS17 RTS

Also, some questions about booting Debian, unrelated to serial ports:

The Raspbian install I'm using uses systemd, and is presumably loading a zillion services that I do not need like disk quotas, "remote file systems", "encrypted volumes", etc. How do I tell what it's doing and how do I identify and disable the useless cruft? ("Replace systemd with something else" is a common suggestion that is harder that it sounds.)

Also how do I make DHCP be non-blocking, that is, get me to a login prompt while the network is still negotiating?

And how do I make rc.local or something similar run as early as possible? Right now it runs very near the end.


Tags: , , , , ,

57 Responses:

  1. Jake Nelson says:

    DTR says "there's a terminal connected, and it's turned on." RTS/CTS say "ok, I want data now/no more data".

    As I recall it.

  2. The "raspi-config" tool, included with Raspbian, allows you to toggle "wait for network".

  3. Ewen McNeill says:

    DTR/DCD are (approximately) logically paired, as are RTS/CTS (eg, Wikipedia table of common RS232 signals). Ie Terminal Ready/Carrier Detected, Ready to Send/Clear to Send. Some quick searching turns up this DB9 RS232 null modem with handshaking example -- for which you'll have to do the DB9 pin name to DB25 pin name if you want to build that as well (the Wikipedia link has DB25 pin numbers). The example looks basically sane from what I remember of my days of dealing with async modems...

    The main difference from what you've done is that I'd normally expect to cross RTS to CTS in each direction in a null modem, as you cross TX to RX in each direction. DTR and DCD are often also hooked together, but not always necessary (depends on the equipment; some won't do anything without DTR/DCD). Off the top of my head I don't think linking DTR and RTS together makes sense, and linking DTR and CTS together wouldn't give you flow control the way you want. (DTS is basically continuously asserted -- "I am a terminal and I am here" -- where as RTS/CTS will come and go depending on data flows and buffer capacity.) Also RS232 is a positive/negative signalling system, so grounding something is "neutral" (unless you're doing it on the TTL side, in which case that would translate as "low" through to RS232).


    PS: The traditional way to debug serial issues is with a serial breakout box that has flashing LEDs showing the status of the lines.

    • jwz says:

      Ok, so maybe what's going on here is that the terminal supports RTS (which it turns off when its input buffer is full) but does not support CTS (that pin being wired to ground, which would mean that it does not allow the other end to tell the terminal "stop sending").

      Perhaps it uses DTR for when it is in "offline" mode or something. Because that line is hooked up to logic, not just to power or ground. DSR isn't even wired up.

      I have a serial cable with LEDs on it, but the CTS/RTS lights are always on even if those pins are not connected, so I am hoping for a way to tell the kernel to "RTS off". If that makes the LED go off, then I know that both: the kernel is doing what I think it should be doing, and I have the right pins connected.

      • Ewen McNeill says:

        It sounds plausible that the "dumb" terminal only supports unidirectional flow control (ie, the terminal can say "wait, wait, I need to catch up" but has no outgoing buffer so is entirely uninterested in the other end saying "I can't keep up with the typist at the keyboard" -- if it's going to be dropped it doesn't really matter if it's dropped on the wire or inside the terminal). In which case you'd only need one direction of RTS/CTS crossing to get the flow control you want; the other probably could be connected but sounds like it'll just be ignored.

        A key RS232 concept is that it is defined asymmetrically. There are DTE devices (Data Terminal Equipment -- "terminals") and DCE devices (Data Communications Equipment -- "modems"). The meanings of the signals are defined with respect to the DTE -> DCE and DCE -> DTE interactions. However in the "local terminal hard wired to the serial port of a host expecting to be a terminal" situation, you have two DTE devices back to back -- hence the null modem. Mostly this means that the meaning of signals like RTS, CTS, etc, change depending on which end you look at. Eg, DCD is an output from the point of view a DCE device ("I am a modem and I see carrier on the line"), but it is an input of a DTE device ("Aha, looks like my attached DCE -- modem -- is seeing carrier"). And thus when you connect two DTE devices together via a null modem, some mental logistics is required to make sense of it all.


        PS: Ingmar's observation "DTR/DCD are basically the session control, while RTS/CTS are the flow control." is the most concise explanation I've seen of how its supposed to work. However in practice... implementations did various other things, as they point out. Your terminal appears to be one of those "not 100% following the complete original RS232 theory" situations. Hopefully its manual explains what it actually expects to happen when hooked to a modem (DCE), and then you can translate that into DTE-speak for the Pi's terminal to create.

        PPS: Being session control DTR is a fairly easily controlled output n a terminal (eg, the Pi, running Linux); and DCD is a fairly easily inspected input on a terminal (eg, the Pi, running Linux). Something like kermit should allow you to control/see those. You might want to experiment with those to understand what the terminal expects.

  4. Noah says:

    `systemctl --all` will show all "units," which includes services
    `systemctl disable [unitname]` should prevent it from being started automatically

    • Rodger says:

      Also: `systemd-analyze` will show you where your boot time is going; `systemd-analyze blame` will sort by most costly service, and `systemd-analyze critical-chain` will show you where your dependencies actually are.

      • jwz says:

        Wow, I am shocked that this exists. I thought this kind of analysis was the sort of thing that Linux avoids at all costs, let alone includes in the default release.

        • Debian's particularly bat-shittiness lies elsewhere. They do tend to like Data.

        • Rodger says:

          It's been a huge, ongoing shitfight to get a certain sort of neckbeard to admit the possibility that systems design could have advanced since 1985. systemd is actually pretty good, overall.

    • Phil says:

      Small addendum: systemd disable won’t actually turn a service off if something else depends on it. You need another command for that, although I can’t for the life of me remember what it is offhand.

      • Karellen says:

        # systemctl mask <service>

        will prevent a service from being loaded, even if another service depends on it.

        (also, you want "systemctl disable" not "systemd disable")

  5. Ingmar says:

    DTR/DCD are basically the session control, while RTS/CTS are the flow control. Back in the days of modems, DTR (Data Terminal Ready) was the terminal telling the modem it was good and ready, and when the terminal dropped DTR, the modem took that as a signal to hang up. In the other direction, the modem would raise DCD (Data Carrier Detect) when it established a session, and drop it when that session ended (and often also say things like "NO CARRIER" in-band).

    RTS/CTS are the flow control. RTS (Request To Send) is the terminal telling the modem "speak now" or "waitwait, my buffer is full, yes, all 8 byte of it" (when lowered). CTS (Clear To Send) is the same for the modem, so when that is lowered, the modem has a full buffer and asks the terminal to stop sending.

    Then there were some perverts that for some weird reason used DTR for flow control, so that's why many terminal emulators have DTR/DCD flow control options. But don't do that when you have perfectly fine RTS/CTS lines.

    And those pairs always go together, DTR/DCD and RTS/CTS. So you'd swap RTS and CTS, and you'd swap DTR/DCD (although you probably don't need those at all). You'd never swap RTS and DTR like you did because that way lies insanity.

    Oh, and there was also a RI (Ring Indicator), which the modem raised when the telephone line was ringing. You can safely ignore that though.

    Wikipedia has the pinout and a helpful table that explains which side gets to control which pins.

  6. Eric Smith says:

    RTS originally had a completely different meaning that what became popular for flow control. The DTE (terminal or computer) asserted RTS when it wanted to transmit, and then the DCE (modem) asserted CTS when it was actually ready for the DTE to transmit. This was back when half-duplex modems were fairly common; since the 1980s almost all modems are full-duplex, and when carrier detect (CD) is asserted, they are always ready for the DTE to send (transmit). With full-duplex modems (or full-duplex connections in general), the original purpose of RTS is obsolete.

    RTS/CTS flow control has repurposed RTS to have NOTHING to do with when the DTE wants to "send" (transmit), and instead the DTE asserts RTS when it is ready to RECEIVE data from the DCE. In recognition of this, the EIA/TIA-232-E standard (successor to RS-232) designates a new "circuit", "Ready To Receive" (RTR), which is assigned the same connector pin as RTS. Obviously that pin can only be used for RTR or RTS at any given time, but not both.

    RTS/CTS flow control should now more properly be called RTR/CTS flow control, but due to historical precedent, no one does that.

  7. deater says:

    Not sure if this is what you're looking for, but this directory has some code I use on Linux to toggle the RTS and DTR lines.


  8. Kaleberg says:

    Are you sure you wouldn't do better with an Arduino handling this protocol and just treating the various RS-232 ports as ordinary digital ports? If you get an Arduino with WiFi you can just pass the serial data on to a real computer. I suppose this is a bit of an ending is mending strategy, but it seems like there is an awful lot of stuff between the bits and what you want.

    • jwz says:

      Having an Arduino mediate the data between a serial port and a Pi, when the Pi already has an onboard serial port with flow control, seems like the very definition of putting more stuff in the way. I'm just trying to turn the thing on.

      • Will says:

        I'm lazy, perhaps, but I've always had better luck with a USB serial dongle than the onboard serial. Unfortunately the flyback transformer on my VT-100 died before I got the chance to try this sort of thing. The VT-100 has enough empty space for a mac mini, really.

      • Kaleberg says:

        In principle I agree with you, but I have spent too many years in the computer business to necessarily agree in practice. I can't recall how many times a particular device, driver or software package did 99.998% of everything I wanted then challenged me inch by inch for the remaining 0.002%. It might be the ability to clear to the end of the line, set an otherwise ordinary hardware mode or just exploit a certain combination of UI element options, but somehow or another the desired configuration would remain beyond reach. That usually meant circumventing the driver, modifying the device or building some horrible kludge that actually delivered 100%. It wasn't just me, but this elusive last bit was a common war story when commiserating with friends in the business.

        You are trying to use a serial line in a certain way, but you have an entire operating system standing in your way. I'm probably projecting my own experience inappropriately, but it might make sense to exploit all the modern cheap hardware and get the OS out of the way. Hook up an Arduino via USB and have it drive the lines directly or have it control a UART to your satisfaction.

        Yes, I know that you will figure out the proper OS configuration, but you aren't trying to meet a deliverable date. Sometimes necessity is the mother of, what in better times, would be called idiocy.

        P.S. I keep thinking of the story an older tech told me. His company tried to cheap out on air conditioning and locked the thermostat. They rigged a soldering iron to keep the AC running. It was like something out of a Phil Silvers comedy.

      • rozzin says:

        ISTR that those Arduino Wi-Fi modules actually ran Linux internally. Having an Arduino mediate between the Pi and the serial port, when that in turn actually involves having an additional Pi-class computer mediate between the Pi and the Arduino..., definitely does seem like just putting more stuff in the way for the sake of putting more stuff in the way.

        You'd also presumably be bridging RS-232 onto TCP over Wi-Fi, or vice versa..., which is... I've never been able to figure out why so many people seem to think that's a good idea.

  9. Dusk says:

    If you want to get rid of systemd, Debian still supports SysV-style init. "apt-get sysvinit-core" will install it.

    Don't expect it to speed up startup, though. In my experience, SysV init is actually a bit slower to get things going.

    • jer says:

      sysvinit is tiny and fast and is done doing most of its work a split second after it starts.

      When you say Debian boots slowly you are referring to the Debian-specific init scripts (that you should not confuse with sysvinit itself) which mostly run sequentially and use all kinds of funky time-outs.

      • Dusk says:

        Well, yes. Thanks for being pedantic. But what matters from a practical perspective isn't how much time it takes init to start up, it's how long it takes the whole system to start up. Which is what I meant.

        • jer says:

          I wasn't being pedantic. I was perhaps trying to rectify a common misunderstanding. The point being that scripting systems like, say, openrc (perhaps supported by dependency graph generating compiled programs), have long replaced Debian's failing attempts at providing an efficient init script system, for other Linux distributions, that is.

  10. Martin says:

    > How do I toggle the RTS line through software?

    If you're just looking to toggle it interactively to see if it lights an LED, this is a good way:

    $ python
    >> from serial import Serial
    >> port = Serial('/dev/whatever')
    >> port.setRTS(1)
    >> port.setRTS(0)

    Likewise you have setDTR, getCTS, getDSR and getCD.

    • jwz says:

      Huh. Well, if I do either setRTS(1) or setRTS(0) (from another terminal), it makes the connection on ttyAMA0 totally lose its mind: starts sending the wrong bytes until getty exits.

      The serial_port C code doesn't seem to do anything at all.

      And neither of them make the LEDs on my serial tester cable change state.

      So I guess I know that the python code is able to do something to the kernel that makes something happen. I still don't have verification that the kernel is affecting pins on the Pi, or that I have my wires on the right pins.

      • deater says:

        Are you using a Pi3?

        You probably know this, but the pi3 switched the primary serial port to hook into the bluetooth adapter and the exported serial pins were remapped to the stripped down mini-uart that doesn't have RTS support.

        I vaguely feel like it's possible to disable bluetooth and switch the uarts back again but it might involve some device tree magic.

        Yes, obnoxious all around, I was foolishly trying to teach an operating systems class where we programmed bare-metal on the Pi and they pulled these games that make each generation of Pi incompatible at the very low level.

        • jwz says:

          Yes, Pi 3 B 1.2, and I think I have it configured to use the real serial port instead of Bluetooth. I'm running my console on ttyAMA0 instead of ttyS0 and did all this rigamarole:


          # Turn on the serial port on GPIO 13/14

          # Move Bluetooth to the mini-UART (ttyS0) and move the serial
          port to the high performance GPIO (ttyAMA0).

          # /boot/overlays/README section on pi3-miniuart-bt says this
          is necessary:


          # After=dev-ttyAMA0.device

          • deater says:

            I should have known you would have done all that already.

            This is a more interesting problem than the stuff I'm supposed to be working on. Most of my equipment is back at my lab, but I do have a pi3 and a multimeter here, I'm going to see if I can get anything out of the RTS line.

        • deater says:

          re-read the old article and you are using a Pi3.

          So one thing to try is to add dtoverlay=pi3-disable-bt to your /boot/config.txt reboot and then retry everything.

          Possibly you also have to disable the hciuart code at boot so bluetooth doesn't try to take over the connection.

          This suggestion is based on the info from this page: https://www.raspberrypi.org/forums/viewtopic.php?t=138223

          • jwz says:

            Using pi3-disable-bt instead of pi3-miniuart-bt seems to necessitate moving everything back to ttyS0 instead of ttyAMA0, but does not magically make flow control start working...

            • deater says:

              OK, so can I assume you are still using rpirtscts to try to enable RTS?

              The one in their git repository is broken for Pi3. The GPIOBASE on pi2/pi3 is at a completely different address.

              There was also an embarassing bug in my toggle_rts C code.

              Anyway I have some code in a new repository here, and with it I can run rpirtscts then pulse_rts and the RTS line (GPIO17) toggles at 1Hz.


              • deater says:

                And of course someone had reported this bug to them back in May but apparently it wasn't worth fixing.

              • jwz says:

                Yeah, I was using that but added a case for bcm2709. Looks like it needed more than that...

                Anyway, now I'm running your code: "rpirtscts on" followed by "pulse_rts", and my cable's LEDs are staying resolutely on.

                Pi 3 Model B Rev 1.2 with 40 pin
                Enabling CTS0 and RTS0 on GPIOs 16 and 17
                Before: fe4000 mask fc0000
                After: fe4000
                GPIO14/15=24 Expect ALT0/ALT0 0x24

                I've got RTS on Pi 3 pin 11 (BCM 17) and CTS on pin 36 (BCM 16). I also tried swapping them.

                • deater says:

                  That all looks like it should :(

                  I have an LED hooked to RTS/pin11/gpio17 and it blinks at 1Hz when I run pulse_rts.

                  In /boot/config.txt the only change I made from stock is dtoverlay=pi3-miniuart-bt

                  Probably not that it matters but I'm running Linux 4.4.30-v7+

                  • jwz says:

                    Ok, progress! I didn't hook up an LED but just poked a voltmeter at it, and pulse_rts is indeed making pin 11 go from 0v to 3.2v at 1Hz!

                    One possibility is that my tester cable is lying to me. Seems unlikely. Also, when hooked up to the AAA, I'm still seeing overruns.

                    Another is that this thing is not implementing RTS/CTS properly. Though it is definitely doing the right thing with RX/TX...

                  • deater says:

                    Not sure why it's not letting me reply to your response.

                    In any case it's quite possible Linux or the BCM2835 are doing stupid things too, I've been burned many times by both of them.

                    Anyway I put together a dump_serial_regs utility you can use while your connection is active to see what the actual pi hardware thinks about your CTS/RTS state.

                    If I fire up minicom it looks like everything gets set properly by the Linux driver, but I actually don't have an adapter with CTS/RTS so I can't test things any further than this.

                  • jwz says:

                    It cuts off nested thread display at depth 8, but if you hit reply from the notification email it puts it in the right place.

                    dump_serial_regs is showing me CTS and RTS enabled, but I haven't seen CTS say anything but "low" or RTS say anything but "0", even while the AAA was beeping because it had overflowed its inbound serial buffer.

                    I ran it in a loop while typing ^L at xemacs to provoke it. "RX FIFO" and "TX FIFO" change from empty/not empty/full, UART becomes busy/not busy, and FR and IMSC registers take on several different values. But not CTS/RTS changes.

                  • deater says:

                    It cuts off nested thread display at depth 8, but if you hit reply from the notification email it puts it in the right place.

                    Ahh, you're assuming I'm not some sort of luddite that still checks e-mail using pine and so I don't always think to click links in e-mails.

                    Anyway you've probably already tried this, but I can verify that if I hook 3.3V directly to the GPIO16/CTS pin the UART_FR CTSin register bit shows the line as going high.

                    So possibly a problem on the incoming signal? Maybe the level converter?

                  • jwz says:

                    Ok, more progress! It turns out the TTL-DB9 dingus has some pins that need to be jumpered to enable RTS/CTS, which I didn't notice because I was a dummy and didn't actually search for a manual. With that set up, my serial tester cable does indeed pulse the light when running pulse_rts, and I see 8.5v toggling on DB9 pin 7! Yay!

                    However, the effect of this when hooked up to the aaa60 is that "rpirtscts on" causes the display to stop updating, and "rpirtscts off" causes it to resume. So it's behaving as if enabling CTS causes CTS to never be asserted.

                    ./dump_serial_regs > a; ./rpirtscts on; ./dump_serial_regs > b; diff -U0 a b
                    Pi 3 Model B Rev 1.2 with 40 pin
                    Enabling CTS0 and RTS0 on GPIOs 16 and 17
                    Before: 24000 mask fc0000
                    After: fe4000
                    GPIO14/15=24 Expect ALT0/ALT0 0x24
                    --- /tmp/a 2016-11-25 13:19:55.280149976 -0800
                    +++ /tmp/b 2016-11-25 13:19:55.290149872 -0800
                    @@ -7,2 +7,2 @@
                    - PIN16/CTS = not configured
                    - PIN17/RTS = not configured
                    + PIN16/CTS = AMBA (ALT3)
                    + PIN17/RTS = AMBA (ALT3)
                    @@ -11 +11 @@
                    - FR register: 19
                    + FR register: 18
                    @@ -17 +17 @@
                    - CTS pin is low
                    + CTS pin is high
                    @@ -31 +31 @@
                    - IMSC register: 7f
                    + IMSC register: 5f

                  • deater says:

                    So I've spent a lot of time digging through this whole mess and I really can't see anything obvious that is wrong.

                    What value does RTS pin have through all this? I'd think in the working state RTS out of the Pi would be 1 and CTS into the Pi would also be 1?

                    Does transmission restart if you manually force RTS to be 1?

                    I was searching for any evidence that anyone has ever successfully gotten hardware flow control on the Pi working and while many have tried and failed I never found a successful report (though maybe no one ever posts good news).

                  • deater says:

                    So some further thoughts.

                    Things working without RTS/CTS pins enabled makes sense. By default the rpi GPIO pins are set to input, which means floating high-impedeance. And the aaa60 manual says that if the CTS input is left floating then it means to allow transmit (and presumably the line is pulled high by a pullup resistor somewhere).

                    When RTS/CTS is enabled though it sounds like the pi is pulling the RTS line low, which is stopping everything. Why is it low? One possibility is that the Pi has the RTS output inverted from what the aaa60 expects (I've come across people talking about having to hack an inverter into the line for some devices to work). Obviously that would be a pain :(

                  • jwz says:

                    So I measured voltages on the DB9. In all cases, CTS stays at +1.3v (between pins 8 and 1, which is wired to signal ground on both Pi and AAA).

                    rpirtscts on: output stops, RTS -5.7v.

                    rpirtscts off: output resumes, RTS +8.9v.

                    rpirtscts on, but unplug GPIO 16: output resumes, RTS: -5.7v.

                    rpirtscts off, pulse_rts: RTS stays at +8.9v.

                    rpirtscts on, pulse_rts: RTS flops between -5.7v and +10.2v (I think: my meter goes a little wonky). Also I kind of expected the display to update for 1 sec then stop, and it doesn't update at all.

                    I am confused about why I am seeing different voltage readings on RTS at all: isn't that communication from the AAA to the Pi? So long as the AAA's serial buffer is not full, it should be sending whatever-voltage-means-go, and when the buffer is full, the opposite.

                    The Pi telling the AAA "my buffer is full" is not a thing that should be able to happen.

                  • deater says:

                    So I finally just went out and bought a rs232 level converter, I think the same model you have.

                    I've hooked up my pi3 to a terminal (in this case an x86 machine running minicom, sadly I don't have any old terminal hardware).

                    Ran agetty on the pi3 in 115200/8/n/1/rtscts mode (had to run it by hand, hate systemd)

                    While connected from the terminal, did a huge screen dump (cat /boot/kernel.img | uuencode -m -)

                    This itself was not enough to kick in the flow control (I guess modern hardware is so good). But if I did something to stop reading the serial line (such as bring up a menu in minicom) the Pi side of the connection went from CTS=0/RTS=0 to CTS=1/RTS=0 and the flow stopped. And when I closed down the menu it went back to CTS=0/RTS=0 and the flow resumed. So I assume this means the flow control is working?

                    My settings, in case it's useful:
                    I'm using a 9-pin null-modem cable

                    PI3 ------- RS232-breakout
                    3.3V ------- VCC
                    GND -------- GND
                    RX(pin10) -- RX
                    TX(pin8) --- TX
                    RTS(pin11) - RTS
                    CTS(pin36) - CTS

                    plus it's jumpered for rts/cts

  11. Ryan says:

    This is at least very adjacent to the kinds of comments you really hate, so I'm really hesitant here. But there is a neat and way under-known project called Alpine Linux that is maybe worth considering since you're already getting pretty fiddly with this:


    It's radically smaller and more streamlined than anything else (and especially Debian), but retains most of the usability/ease. So while I know your feelings about Linux-fiddling, this isn't totally that, and I also know your feelings about Debian....

    Runs on the Pi: https://wiki.alpinelinux.org/wiki/Raspberry_Pi though I don't know enough about what you're trying to accomplish overall to know if it's a good fit for you.

  12. rcp says:

    To make rc.local run as early as possible change the sort order of the symlink:

    runlvl=$(runlevel | cut -c3-)
    cd /etc/rc${runlvl}.d && sudo mv S*rc.local S00rc.local

    Stop reading if this works for you.

    I don't know what the rpi environment puts into rc.local by default, and it traditionally runs last, so check that there's nothing in there that's not going to like running early.

    On older debian systems the Right Thing to do would be to use the update-rc.d command to change the symlinks.

    update-rc.d -f $service \
    start $start_order $start_levels . \
    stop $stop_order $stop_levels .

    YMMV. This may be yet another thing that I used to know how to do that is now obsolete.

    • jwz says:

      The real answer seems to be to remove "After=network.target" from /lib/systemd/system/rc-local.service.

      Allowing getty and other services to start initializing before DHCP handshaking is complete seems to be accomplished by replacing "auto" with "allow-hotplug" in /etc/network/interfaces.

    • nodak1999 says:

      Changing the number on the rc script would still be the easy thing to do, had SysVinit not been needlessly replaced with something "modern". systemd is a gaping head wound.

  13. jwz said:

    (Fun fact that I managed to go my entire life until today without realizing, which suddenly explains so many things: did you know that the RS232 DB25 spec has TX/RX on pins 2/3, but the RS232 DB9 spec swaps them to 3/2? And that is not for a null modem.)

    Wait, what? I mean, obviously, the pins aren't going to line up, and hoping that the DB9 ports would just map to the first 9 on the DB25 but what super-villain decided straight numerically swapping RX/TX's pin numbers would be a neat prank to play on the world? Yeesh.

  14. jwz says:

    It's really starting to bug me that cmatrix is not optimized for low-baud-rate devices...

    No. I'm not doing this. No no no no no.

    • David Ashby says:

      Just low-baud-rate? I just installed it on my mac and full-screened the terminal and that redraw rate is abysmal...

      • jwz says:

        So of course cmatrix is just using ncurses to do the obvious thing in the obvious way, and surprise surprise... apparently ncurses's idea of how you "optimize" that screen update between the old array and the new array is you start at the top left and move right, and if as soon as there is a single character of difference, you move the cursor there and overwrite it.


        What makes this so amazing is that every time I have ever updated a Linux system in the last two decades, every time, there's a new version of ncurses. More than once I've yelled at the screen, WHAT THE FUCK ARE THEY CHANGING IN NCURSES! STOP! STOP TOUCHING THAT! IT'S DONE! I've never actually looked at the diffs, but seriously, every time!

        I assume they're updating the licensing terms or localization strings or something, because hey, that too should be an ongoing area of innovation in code that literally should not have changed since 1992. But come on.

        Anyway, it's good to know that the one thing that hasn't changed, and that they never got right, is the thing Emacs was doing properly by 1981 at the latest.

        And let's not forget that this is ncurses. The new version of curses. Because it's supposedly better than plain-old curses was in some way. Some way apparently unrelated to getting characters onto your screen efficiently.

        • How I feel when I run pkg to update packages on FreeBSD and before it can figure out what packages to update it first has to update itself. Happens about half the time. Why isn't pkg DONE?

        • ncurses was last updated fifteen months ago. I checked out its website and noticed this.

          Output buffering provided a further, but worthwhile distraction. A bug report in 2012 regarding the use of signal handlers in ncurses) pointed out a problem with the use of unsafe functions for handling SIGTSTP. Other signals could be addressed with workarounds; repairing SIGTSTP required a different approach. The solution required changing internal behavior of the library: how it handles output buffering.

          Now ncurses buffers its own output, independently of the standard output. A few applications relied upon the library's direct reuse of the standard output buffering; however that is unspecified behavior and has never been a recommended practice. Identifying these applications as well as refining the change to permit low-level applications to work consistently took time.

          It's ugly hacks all the way down.

  15. spanner says:

    I haven't seen CTS say anything but "low" or RTS say anything but "0", even while the AAA was beeping because it had overflowed its inbound serial buffer.

    That's telling, and not in a good way. RTS from AAA (CTS to RPi) matters here, other direction not so much. Could there be a setting (DIP switch?) in the AAA to make it drop (raise/change/whatever) its RTS on a full buffer?

  16. Just an FYI, Adafruit now has a neat little Serial to USB board for about $6 that claims to understand flow control. Probably way too late for this project, but probably useful in the future for turning ancient terminals into USB devices. (Yes, one can also use a standard USB to Serial dongle, though this gives you the ability to directly wire whatever signals you want a bit more conveniently.) I'm posting it here partially because I bet someone will end up trawling this blog post someday and will want to know.

  • Previously