v0.2: improved serial i/o significantly
This commit is contained in:
@@ -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")
|
||||
|
Reference in New Issue
Block a user