v0.2: improved serial i/o significantly

This commit is contained in:
Torsten Harenberg
2022-06-30 11:10:13 +02:00
parent 593d09ae91
commit 709e47a585
9 changed files with 131 additions and 91 deletions

View File

@@ -6,7 +6,7 @@ import (
"errors"
"fmt"
"github.com/albenik/go-serial/v2"
"github.com/go-playground/log/v7"
"github.com/go-playground/log/v8"
"github.com/schollz/progressbar/v3"
"io/ioutil"
"os"
@@ -25,14 +25,14 @@ type modem struct {
}
// initmodem: opens the serial line, returns instance of serial.Port
func initmodem(serport string, baudrate int, sertimeout int) (*modem, error) {
func initmodem(serport string, baudrate int) (*modem, error) {
p, err := serial.Open(serport,
serial.WithBaudrate(baudrate),
serial.WithDataBits(8),
serial.WithParity(serial.NoParity),
serial.WithStopBits(serial.OneStopBit),
serial.WithReadTimeout(sertimeout),
serial.WithWriteTimeout(sertimeout))
serial.WithReadTimeout(-1), //blocking I/O, see https://pkg.go.dev/github.com/albenik/go-serial#Port
serial.WithWriteTimeout(-1)) //blocking I/O
if err != nil {
fmt.Printf("ERROR: File %s could not be opened\n", serport)
return nil, err
@@ -41,9 +41,10 @@ func initmodem(serport string, baudrate int, sertimeout int) (*modem, error) {
return m, nil
}
// write: writes to the serial ports, returns answer and logs output
func (m *modem) write(out string, nolog ...bool) ([]byte, error) {
if len(nolog) == 0 {
// write: writes to the serial ports, returns answer and logs output. Optional toread forces a
// certain number of bytes to read
func (m *modem) write(out string, toread ...uint32) ([]byte, error) {
if len(toread) == 0 {
log.Debug("Sending " + strings.TrimFunc(out, func(r rune) bool {
return !unicode.IsGraphic(r)
}))
@@ -52,18 +53,37 @@ func (m *modem) write(out string, nolog ...bool) ([]byte, error) {
log.Debugf("Sending %d byte(s)", len(out))
}
}
_, err := m.port.Write([]byte(out))
if err != nil {
log.Errorf("ERROR while sending serial command: %s\n", out)
log.Error(err)
return []byte(""), err
for {
status, err := m.port.GetModemStatusBits()
if err != nil {
log.Fatal("GetModemStatusBits failed")
}
if status.CTS {
for {
sent, err := m.port.Write([]byte(out))
if err == nil {
break
} else {
// log.Errorf("ERROR while sending serial command: %s\n", out)
log.Debug(err)
out = out[sent:]
}
}
break
}
}
buff := make([]byte, 1024)
if len(nolog) == 0 {
time.Sleep(50 * time.Millisecond) // give the PTC some time to answer, no needed with binary
var btr uint32
if len(toread) == 0 {
time.Sleep(80 * time.Millisecond) // give the PTC some time to answer, no needed with binary
btr, _ = m.port.ReadyToRead()
if btr == 0 {
return []byte(""), nil
}
} else {
btr = toread[0]
}
buff := make([]byte, btr)
n, err := m.port.Read(buff)
// fmt.Printf("Read %d bytes\n", n)
if err != nil {
log.Errorf("ERROR: cannot read answer from command: %s\n", out)
return []byte(""), err
@@ -103,27 +123,29 @@ func (m *modem) setDateTime() error {
// writeUpdate: main flash utility. Writes the firmware taken from fwfile to the modem. Write progress bar.
func (m *modem) writeUpdate(fwfile string) error {
m.port.SetWriteTimeout(-50)
m.port.SetReadTimeout(-1)
_, err := m.write("UPDATE\r")
if err != nil {
_, _ = m.write("\033", true) // send ESC to cancel the update
_, _ = m.write("\033") // send ESC to cancel the update
return err
}
answer, err := m.write("\006", true)
answer, err := m.write("\006")
if err != nil {
_, _ = m.write("\033", true) // send ESC to cancel the update
fmt.Println(err)
_, _ = m.write("\033") // send ESC to cancel the update
return err
}
log.Debugf("flash stamp: % X", binary.LittleEndian.Uint32(answer[2:6]))
flashId := binary.LittleEndian.Uint16(answer[0:2])
log.Debugf("flash id: % X", flashId)
if flashId != 0xa41f && flashId != 0x5b1f && flashId != 0xda1f {
_, _ = m.write("\033", true) // send ESC to cancel the update
_, _ = m.write("\033") // send ESC to cancel the update
return errors.New("wrong flash id")
}
r, err := os.Open(fwfile)
if err != nil {
_, _ = m.write("\033", true) // send ESC to cancel the update
_, _ = m.write("\033") // send ESC to cancel the update
return err
}
fstat, _ := r.Stat()
@@ -132,7 +154,7 @@ func (m *modem) writeUpdate(fwfile string) error {
fwblob, err := ioutil.ReadFile(fwfile)
if err != nil {
_, _ = m.write("\033", true) // send ESC to cancel the update
_, _ = m.write("\033") // send ESC to cancel the update
return err
}
// fmt.Println(fsize)
@@ -140,20 +162,20 @@ func (m *modem) writeUpdate(fwfile string) error {
if fsize%256 != 0 {
chunks++
}
// send ACK
_, err = m.write("\006", true)
_, err = m.write("\006")
if err != nil {
_, _ = m.write("\033", true) // send ESC to cancel the update
_, _ = m.write("\033") // send ESC to cancel the update
return err
}
// send number of chunks
a := make([]byte, 2)
binary.BigEndian.PutUint16(a, chunks)
res, err := m.write(string(a), true)
res, err := m.write(string(a))
if err != nil || string(res) != "\006" { //no ACK
_, _ = m.write("\033", true) // send ESC to cancel the update
fmt.Println("kein ACK")
_, _ = m.write("\033") // send ESC to cancel the update
return err
}
@@ -168,15 +190,15 @@ func (m *modem) writeUpdate(fwfile string) error {
} else {
sendbuff = string(fwblob[i*CHUNKSIZE : i*CHUNKSIZE+CHUNKSIZE])
}
res, err = m.write(sendbuff, true)
res, err = m.write(sendbuff, 1)
if err != nil || string(res) != "\006" { //no ACK
_, _ = m.write("\033", true) // send ESC to cancel the update
log.Errorf("Error in Handshake! Rx: %s", hex.EncodeToString(res))
_, _ = m.write("\033") // send ESC to cancel the update
return err
}
}
log.Infof("Firmware file %s successfully written", fwfile)
_, err = m.write("\r", true)
_, err = m.write("\r")
if err != nil {
log.Error("Error in Handshake: cannot send final cr")
}
@@ -226,8 +248,8 @@ func (m *modem) checkFirmwareFits(fwfile string) error {
}
// Update: main firmware update utility. Runs pre-checks and calls main flashing function writeUpdate
func Update(serport string, baudrate int, sertimeout int, fwfile string, force bool) error {
m, err := initmodem(serport, baudrate, sertimeout)
func Update(serport string, baudrate int, fwfile string, force bool) error {
m, err := initmodem(serport, baudrate)
defer m.port.Close()
if err != nil {
return errors.New("FEHLER in Update")