bugst / go-serial

A cross-platform serial library for go-lang.
BSD 3-Clause "New" or "Revised" License
622 stars 191 forks source link

Darwin 64-bit not sending #9

Closed jcw closed 7 years ago

jcw commented 7 years ago

I can't get the 64-bit version of this package to work on macOS:

package main

import (
    "go.bug.st/serial.v1"
    "time"
)

func main() {
    tty, err := serial.Open("/dev/cu.usbserial-A600dW4s", &serial.Mode{
        BaudRate: 115200,
    })
    if err != nil {
        panic(err)
    }

    for {
        tty.Write([]byte("xxxxxxxxxxxxxxxxxxxxxxxxxx"))
        time.Sleep(time.Second)
    }
}

This works: GOOS=darwin GOARCH=386 go run try.go and blinks the TX LED. This doesn't: GOOS=darwin GOARCH=amd64 go run try.go.

jcw commented 7 years ago

Intriguing... output works with one USB serial adapter, but not another (serial IN is fine).

jcw commented 7 years ago

It looks like the 32-bit macOS build doesn't work fully either. I have not been able to detect an attached STM32 microcontroller, when it's powered up in boot mode (which uses 8N1 even parity).

jcw commented 7 years ago

Could this be the solution? - https://github.com/Adapptor/go-serial/blob/master/serial/open_darwin.go#L185-L204

cmaglie commented 7 years ago

Hi @jcw can you please provide more context on what you're trying to do and what the code on the STM32 should do?

Could you also check the error reported from Write? something like this:

n, err := port.Write([]byte("xxxxxxxxxxxxxxxxxxxx"))
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Sent %v bytes\n", n)
jcw commented 7 years ago

Hello Christian, thanks - here's what I see:

$ go run try.go
Sent 26 bytes
Sent 26 bytes
Sent 26 bytes

No blink - BUT: when I change the baud rate to 9600, there's a very clear blink. Woohoo! - it works on 9600 baud. Maybe there's a typo in the baud constants table?

... or maybe the OUTPUT baudrate is not being set? ...

cmaglie commented 7 years ago

The constant table is here https://github.com/bugst/go-serial/blob/v1/serial_darwin.go#L16 and it seems correct (well there isn't much we can do wrong there).

But tell me: is it working for both 386 and amd64 now? from what I've understood:

115200 with amd64 -> working 115200 with 386 -> NOT working 9600 with 386 -> working

is that right?

jcw commented 7 years ago

I can confirm that up to 57600, things work:

go build && ./folie -p /dev/cu.usbserial-A600dW4s -b 57600
[connected]
upload mecrisp
  20280b + v22 #0410 R +W +E writing: 80/80 done.

That's a firmware upload using 8-bit even parity - note that I have to switch parity on and off to perform this upload, so that could also be a place where the baudrate setting could be messed up.

cmaglie commented 7 years ago

ok thanks that's enough to investigate.

I'll take a look later, I've to go AFK now.

jcw commented 7 years ago

My findings: upload works on 9600 & 57600, not on 115200 & 230400 - same for 386 and amd64. When not working, I can see incoming data, but no outgoing LED blips.

jcw commented 7 years ago

It's more complex: open no parity, no upload (i.e. plain terminal) - works on 386, not amd64. But same open, then switch to even parity for upload: doesn't work on 386 or amd64.

It's not this machine, I can do a 115200 baud upload with another utility on the same connection. And incoming data in terminal mode is properly received @ 115200 Bd, also on amd64.

UPDATE - here is my latest attempt to work around this issue:

In other words, after a switch to/from the upload settings, the 386 build no longer sends out any data at 115200 Bd, even though it continues to receive and display incoming data properly.

I hope these notes will allow you to narrow down this issue and resolve it. My code is on GitHub in the "bugst" branch. Cheers -jcw

cmaglie commented 7 years ago

@jcw I tried the first snippet that you posted:

package main

import (
    "go.bug.st/serial.v1"
    "time"
)

func main() {
    tty, err := serial.Open("/dev/cu.usbmodemFD121", &serial.Mode{
        BaudRate: 115200,
    })
    if err != nil {
        panic(err)
    }

    for {
        tty.Write([]byte("xxxxxxxxxxxxxxxxxxxxxxxxxx"))
        time.Sleep(time.Second)
    }
}

on a 64 bit macosx, and everything is working fine, here the output from my "test-bed":

115200 11 N81
xxxxxxxxxxxxxxxxxxxxxxxxxx115200 11 N81
115200 11 N81
115200 11 N81
115200 11 N81
xxxxxxxxxxxxxxxxxxxxxxxxxx115200 11 N81
115200 11 N81
115200 11 N81
115200 11 N81
xxxxxxxxxxxxxxxxxxxxxxxxxx115200 11 N81
115200 11 N81
115200 11 N81
115200 11 N81
xxxxxxxxxxxxxxxxxxxxxxxxxx115200 11 N81
115200 11 N81
115200 11 N81

As you can see the speed is set correctly and the string of "xxx" is sent too.

I tried also the following:

func main() {
        port, err := serial.Open("/dev/cu.usbmodemFD121", &serial.Mode{})
        if err != nil {
                log.Fatal(err)
        }
        speed := 115200

        fmt.Println("N81")
        port.SetMode(&serial.Mode{ BaudRate: speed, Parity: serial.NoParity, DataBits: 8, StopBits: serial.OneStopBit })
        time.Sleep(time.Second*5)

        fmt.Println("E81")
        port.SetMode(&serial.Mode{ BaudRate: speed, Parity: serial.EvenParity, DataBits: 8, StopBits: serial.OneStopBit })
        time.Sleep(time.Second*5)

        fmt.Println("N81")
        port.SetMode(&serial.Mode{ BaudRate: speed, Parity: serial.NoParity, DataBits: 8, StopBits: serial.OneStopBit })
        time.Sleep(time.Second*5)

        fmt.Println("O81")
        port.SetMode(&serial.Mode{ BaudRate: speed, Parity: serial.OddParity, DataBits: 8, StopBits: serial.OneStopBit })
        time.Sleep(time.Second*5)

        fmt.Println("N81")
        port.SetMode(&serial.Mode{ BaudRate: speed, Parity: serial.NoParity, DataBits: 8, StopBits: serial.OneStopBit })
        time.Sleep(time.Second*5)
}

with all the combination: 115200 with GOARCH=386 115220 with GOARCH=amd64 9600 with GOARCH=386 9600 wit GOARCH=amd64

and everything is working fine here too... To be honest I only have a 64bit mac to try, but when I do:

GOARCH=386 go run test.go

the program is run without any issue. I don't know if this is determinant to reproduce the problem.

Questions: Are you sure that the connection is not working on your side? how do you determine that is not working?

also, I need a piece of program to reproduce the problem. If I can't reproduce here I hardly be able to solve it...

Tomorrow I'll try with another USB2Serial converter to see if there are problems.

jcw commented 7 years ago

Many thanks - this is indeed very odd. Good to know that it works on your setup.

I can confirm (with screen, for example) that each byte sent out clearly shows up on the TX LED, even at 115200 Bd. When the problem occurs, nothing comes out of the port. If I then start the Python-based stm32loader.py, that works properly - without unplugging or port change.

I will test again tomorrow, with a fresh reboot and on a different Mac. A bug in the FTDI driver or a messed up kext setup here would not totally surprise me.

jcw commented 7 years ago

The issue appears to be ClearToSend: when CTS is tied low on the FTDI pin, then everything works!

I'm at a total loss to explain how this can have anything to do with the baudrate ??? And why it's only a problem on the FTDI interface (based on the FT232 chip).

jcw commented 7 years ago

So to summarise: can receive, but can't send on (some?) USB serial interface boards when CTS is not tied to GND (which means "active"). Oddly enough it only happens at 115200 baud and higher.

This sounds suspiciously like "hardware flow control" to me. I wonder why it would be enabled...

cmaglie commented 7 years ago

Oh that explains it, if CTS is not connected to ground (or to the corresponding RTS pin of the UART on the "other side" to make a real flow control) it means that the pin is "floating" and it's basically in an undefined state, it behaves like an antenna that can intercept electromagnetic fields in the nearing. Probably running the UART at high speeds produce more EMF noise, enough to set CTS pin high.

Now the question is: why is the hardware control enabled? it may be enabled by default on the FTDI chip? I found this article http://www.ftdichip.com/Support/FAQs.htm#HwGen3

Let's try to explicitly disable it, I'll post a possible patch in a minute

cmaglie commented 7 years ago

fixed by #10