Compare commits
11 Commits
6e6f61d04b
...
9bb1bcc70f
Author | SHA1 | Date |
---|---|---|
S.J.R. van Schaik | 9bb1bcc70f | 7 years ago |
S.J.R. van Schaik | a7021ab486 | 7 years ago |
S.J.R. van Schaik | 4e10ada708 | 7 years ago |
S.J.R. van Schaik | f2dda00741 | 7 years ago |
S.J.R. van Schaik | 20e650f7e6 | 7 years ago |
S.J.R. van Schaik | 55b4590779 | 7 years ago |
S.J.R. van Schaik | 78ebcafaea | 7 years ago |
S.J.R. van Schaik | 42813ee82b | 7 years ago |
S.J.R. van Schaik | e611220f47 | 7 years ago |
S.J.R. van Schaik | ba4a9b22f0 | 7 years ago |
S.J.R. van Schaik | 6e5bf54598 | 7 years ago |
@ -0,0 +1,245 @@ |
|||||||
|
package main |
||||||
|
|
||||||
|
import ( |
||||||
|
"flag" |
||||||
|
"fmt" |
||||||
|
"log" |
||||||
|
"os" |
||||||
|
"strconv" |
||||||
|
"time" |
||||||
|
) |
||||||
|
|
||||||
|
type CommandFunc func(tbm *TBM, args []string) error |
||||||
|
|
||||||
|
var ( |
||||||
|
serial_device = flag.String("serial-device", "/dev/ttyUSB0", "Serial device to use") |
||||||
|
serial_baudrate = flag.Int("serial-baud", 9600, "Serial baud rate") |
||||||
|
|
||||||
|
commands = map[string]CommandFunc{ |
||||||
|
"echo": cmd_echo, |
||||||
|
"jtag": cmd_jtag, |
||||||
|
"buzzer": cmd_buzzer, |
||||||
|
"led": cmd_led, |
||||||
|
"reset": cmd_reset, |
||||||
|
"flash_probe": cmd_flash_probe, |
||||||
|
"flash_release": cmd_flash_release, |
||||||
|
"flash_info": cmd_flash_info, |
||||||
|
"flash_read": cmd_flash_read, |
||||||
|
"flash_erase": cmd_flash_erase, |
||||||
|
"ftl_probe": cmd_ftl_probe, |
||||||
|
"date": cmd_date, |
||||||
|
"time": cmd_time, |
||||||
|
"set-date": cmd_set_date, |
||||||
|
"set-time": cmd_set_time, |
||||||
|
"sync-time" : cmd_sync_time, |
||||||
|
"mount": cmd_mount, |
||||||
|
"umount": cmd_umount, |
||||||
|
"format": cmd_format, |
||||||
|
"mkdir": cmd_mkdir, |
||||||
|
"rmdir": cmd_rmdir, |
||||||
|
"ls": cmd_ls, |
||||||
|
"stat": cmd_stat, |
||||||
|
"cat": cmd_cat, |
||||||
|
"write": cmd_write, |
||||||
|
"append": cmd_append, |
||||||
|
"mv": cmd_mv, |
||||||
|
"cp": cmd_cp, |
||||||
|
"rm": cmd_rm, |
||||||
|
} |
||||||
|
) |
||||||
|
|
||||||
|
func cmd_generic(tbm *TBM, command string, args []string, payload []byte) error { |
||||||
|
cmd := &Command{command, args, payload} |
||||||
|
tbm.Commands <- cmd |
||||||
|
res := <-tbm.Results |
||||||
|
|
||||||
|
if res.errcode[0] != '0' { |
||||||
|
return fmt.Errorf("Error: %s", res.errcode) |
||||||
|
} |
||||||
|
fmt.Printf("%s", res.output) |
||||||
|
|
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_echo(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "echo", args, nil); |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_jtag(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "jtag", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_buzzer(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "buzzer", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_led(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "led", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_reset(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "reset", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_flash_probe(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "flash_probe", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_flash_release(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "flash_release", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_flash_info(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "flash_info", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_flash_read(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "flash_read", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_flash_erase(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "flash_erase", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_ftl_probe(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "ftl_probe", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_date(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "date", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_time(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "time", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_set_date(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "set_date", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_set_time(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "set_time", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_sync_time(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "set_time", []string{strconv.FormatInt( |
||||||
|
time.Now().Unix(), 10)}, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_mount(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "mount", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_umount(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "umount", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_format(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "format", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_mkdir(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "mkdir", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_rmdir(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "rmdir", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_ls(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "ls", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_stat(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "stat", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_cat(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "cat", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_write(tbm *TBM, args []string) error { |
||||||
|
f, _ := os.Open(args[0]) |
||||||
|
defer f.Close() |
||||||
|
|
||||||
|
buf := make([]byte, 256) |
||||||
|
|
||||||
|
n, err := f.Read(buf) |
||||||
|
|
||||||
|
if n == 0 { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
cmd_generic(tbm, "write", []string{args[1]}, buf) |
||||||
|
|
||||||
|
for { |
||||||
|
n, err = f.Read(buf) |
||||||
|
|
||||||
|
if n == 0 { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
cmd_generic(tbm, "append", []string{args[1]}, buf) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_append(tbm *TBM, args []string) error { |
||||||
|
var n int |
||||||
|
var err error |
||||||
|
|
||||||
|
f, _ := os.Open(args[0]) |
||||||
|
defer f.Close() |
||||||
|
|
||||||
|
buf := make([]byte, 256) |
||||||
|
|
||||||
|
for { |
||||||
|
n, err = f.Read(buf) |
||||||
|
|
||||||
|
if n == 0 { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
cmd_generic(tbm, "append", []string{args[1]}, buf) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_mv(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "mv", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_cp(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "cp", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func cmd_rm(tbm *TBM, args []string) error { |
||||||
|
return cmd_generic(tbm, "rm", args, nil) |
||||||
|
} |
||||||
|
|
||||||
|
func main() { |
||||||
|
flag.Parse() |
||||||
|
|
||||||
|
args := flag.Args() |
||||||
|
if len(args) == 0 { |
||||||
|
log.Fatalf("Please specify at least one command") |
||||||
|
} |
||||||
|
command := args[0] |
||||||
|
|
||||||
|
command_function, ok := commands[command] |
||||||
|
|
||||||
|
if !ok { |
||||||
|
log.Fatalf("Unknown command: %s", command) |
||||||
|
} |
||||||
|
|
||||||
|
t := &TBM{} |
||||||
|
err := t.Connect(*serial_device, *serial_baudrate) |
||||||
|
if err != nil { |
||||||
|
log.Fatal(err) |
||||||
|
} |
||||||
|
t.Handle() |
||||||
|
defer t.Close() |
||||||
|
|
||||||
|
err = command_function(t, args[1:]) |
||||||
|
if err != nil { |
||||||
|
log.Fatal(err) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,30 @@ |
|||||||
|
#!/bin/sh |
||||||
|
|
||||||
|
die() |
||||||
|
{ |
||||||
|
echo $1 |
||||||
|
exit -1 |
||||||
|
} |
||||||
|
|
||||||
|
echo -n "Synchronizing time... " |
||||||
|
timeout 1 ./admin -serial-baud 115200 sync-time || die "ERROR" |
||||||
|
|
||||||
|
echo -n "Identifying flash chip... " |
||||||
|
timeout 1 ./admin -serial-baud 115200 flash_probe 1>/dev/null || die "ERROR" |
||||||
|
timeout 1 ./admin -serial-baud 115200 flash_info |
||||||
|
|
||||||
|
echo -n "Erasing flash chip..." |
||||||
|
timeout 60 ./admin -serial-baud 115200 flash_erase 0x0 0x100 1>/dev/null || die "ERROR" |
||||||
|
echo "OK" |
||||||
|
|
||||||
|
echo -n "Formatting flash chip... " |
||||||
|
timeout 10 ./admin -serial-baud 115200 ftl_probe || die "ERROR" |
||||||
|
timeout 10 ./admin -serial-baud 115200 format || die "ERROR" |
||||||
|
echo "OK" |
||||||
|
|
||||||
|
echo -n "Testing filesystem..." |
||||||
|
timeout 10 ./admin -serial-baud 115200 mount || die "ERROR" |
||||||
|
timeout 10 ./admin -serial-baud 115200 mkdir test || die "ERROR" |
||||||
|
timeout 10 ./admin -serial-baud 115200 ls | grep -Fqe "test" || die "ERROR" |
||||||
|
timeout 10 ./admin -serial-baud 115200 rmdir test || die "ERROR" |
||||||
|
echo "OK" |
@ -0,0 +1,170 @@ |
|||||||
|
package main |
||||||
|
|
||||||
|
import ( |
||||||
|
"fmt" |
||||||
|
"io" |
||||||
|
"log" |
||||||
|
"strings" |
||||||
|
"time" |
||||||
|
|
||||||
|
"github.com/tarm/serial" |
||||||
|
) |
||||||
|
|
||||||
|
type TBM struct { |
||||||
|
Commands chan *Command |
||||||
|
Results chan *Result |
||||||
|
Port *serial.Port |
||||||
|
} |
||||||
|
|
||||||
|
type Command struct { |
||||||
|
command string |
||||||
|
args []string |
||||||
|
payload []byte |
||||||
|
} |
||||||
|
|
||||||
|
type Result struct { |
||||||
|
output []byte |
||||||
|
errcode []byte |
||||||
|
} |
||||||
|
|
||||||
|
func (t *TBM) Connect(device string, baud int) error { |
||||||
|
t.Commands = make(chan *Command) |
||||||
|
t.Results = make(chan *Result) |
||||||
|
|
||||||
|
serialconfig := &serial.Config{Name: device, Baud: baud} |
||||||
|
|
||||||
|
port, err := serial.OpenPort(serialconfig) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
t.Port = port |
||||||
|
|
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
func (t *TBM) Handle() error { |
||||||
|
go handleResults(t.Port, t.Results) |
||||||
|
go handleCommands(t.Port, t.Commands) |
||||||
|
|
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
func (t *TBM) Close() { |
||||||
|
t.Port.Close() |
||||||
|
} |
||||||
|
|
||||||
|
func deserialise(in io.Reader, init []byte) (*Result, []byte, error) { |
||||||
|
var ( |
||||||
|
output, errorcode []byte |
||||||
|
data, rest []byte |
||||||
|
) |
||||||
|
|
||||||
|
want_output := true |
||||||
|
_ = copy(data, init) |
||||||
|
|
||||||
|
for { |
||||||
|
buf := make([]byte, 4096) |
||||||
|
n, err := in.Read(buf) |
||||||
|
if err != nil { |
||||||
|
return nil, nil, err |
||||||
|
} |
||||||
|
|
||||||
|
n2 := n + len(data) |
||||||
|
|
||||||
|
data = append(data, buf[:n]...) |
||||||
|
|
||||||
|
for i := 0; i < n2; i++ { |
||||||
|
// '\r' is really '\n'
|
||||||
|
if data[i] == '\r' { |
||||||
|
data = append(data[:i], data[i+1:]...) |
||||||
|
n2-- |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
if data[i] == 0x4 { |
||||||
|
if want_output { |
||||||
|
want_output = false |
||||||
|
output = data[:i] |
||||||
|
data = data[i+1:] |
||||||
|
// The TBM gives us our own commands back
|
||||||
|
for j := 0; j < len(output); j++ { |
||||||
|
if output[j] == '\n' { |
||||||
|
output = output[j+1:] |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
break |
||||||
|
} else { |
||||||
|
errorcode = data[:i] |
||||||
|
|
||||||
|
rest = data[i+1:] |
||||||
|
return &Result{output, errorcode}, rest, nil |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
func handleResults(in io.Reader, c chan *Result) { |
||||||
|
var ( |
||||||
|
res *Result |
||||||
|
rest []byte |
||||||
|
err error |
||||||
|
) |
||||||
|
|
||||||
|
for { |
||||||
|
res, rest, err = deserialise(in, rest) |
||||||
|
|
||||||
|
if err != nil { |
||||||
|
log.Fatal(err) |
||||||
|
} |
||||||
|
|
||||||
|
c <- res |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func serialise(out io.Writer, command string, args []string, payload []byte) error { |
||||||
|
var quoted_args []string |
||||||
|
var err error |
||||||
|
|
||||||
|
quoted_args = append(quoted_args, command) |
||||||
|
|
||||||
|
for _, arg := range args { |
||||||
|
quoted_args = append(quoted_args, fmt.Sprintf("\"%s\"", arg)) |
||||||
|
} |
||||||
|
|
||||||
|
out_string := strings.Join(quoted_args, " ") |
||||||
|
|
||||||
|
output := []byte(out_string) |
||||||
|
output = append(output, '\r') |
||||||
|
|
||||||
|
_, err = out.Write(output) |
||||||
|
// err is non nil if n != len(output)
|
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
if payload == nil { |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
// FIXME: wait for command to finish
|
||||||
|
time.Sleep(time.Second) |
||||||
|
|
||||||
|
output = append(payload, 0x4) |
||||||
|
_, err = out.Write(output) |
||||||
|
|
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
func handleCommands(out io.Writer, c chan *Command) { |
||||||
|
for command := range c { |
||||||
|
err := serialise(out, command.command, command.args, command.payload) |
||||||
|
if err != nil { |
||||||
|
log.Fatal(err) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue