Skip to content

Commit 2687ff3

Browse files
committed
Add fw updater for u-blox SARA R410M
1 parent f379fac commit 2687ff3

File tree

7 files changed

+336
-2
lines changed

7 files changed

+336
-2
lines changed
517 KB
Binary file not shown.

firmwares/SARA/5.6A2_01_to_99.pkg

1.7 KB
Binary file not shown.

firmwares/SARA/99_to_5.6A2_01.pkg

1.68 KB
Binary file not shown.
11 KB
Binary file not shown.

src/github.com/arduino-libraries/WiFi101-FirmwareUpdater/cli/main/main.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"github.com/arduino-libraries/WiFi101-FirmwareUpdater/context"
66
"github.com/arduino-libraries/WiFi101-FirmwareUpdater/nina"
77
"github.com/arduino-libraries/WiFi101-FirmwareUpdater/winc"
8+
"github.com/arduino-libraries/WiFi101-FirmwareUpdater/sara"
89
"log"
910
"strings"
1011
)
@@ -20,7 +21,7 @@ func init() {
2021
flag.StringVar(&ctx.FWUploaderBinary, "flasher", "", "firmware upload binary (precompiled for the right target)")
2122
flag.StringVar(&ctx.BinaryToRestore, "restore_binary", "", "firmware upload binary (precompiled for the right target)")
2223
flag.StringVar(&ctx.ProgrammerPath, "programmer", "", "path of programmer in use (avrdude/bossac)")
23-
flag.StringVar(&ctx.Model, "model", "", "module model (winc or nina)")
24+
flag.StringVar(&ctx.Model, "model", "", "module model (winc, nina or sara)")
2425
}
2526

2627
func main() {
@@ -32,7 +33,9 @@ func main() {
3233

3334
if ctx.Model == "nina" || strings.Contains(ctx.FirmwareFile, "NINA") || strings.Contains(ctx.FWUploaderBinary, "NINA") {
3435
nina.Run(ctx)
35-
} else {
36+
} else if ctx.Model == "winc" || strings.Contains(ctx.FirmwareFile, "WINC") || strings.Contains(ctx.FWUploaderBinary, "WINC"){
3637
winc.Run(ctx)
38+
} else {
39+
sara.Run(ctx)
3740
}
3841
}
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*
2+
flasher.go - A firmware uploader for the WiFi101 module.
3+
Copyright (c) 2015 Arduino LLC. All right reserved.
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package sara
21+
22+
import (
23+
serial "github.com/facchinm/go-serial"
24+
"time"
25+
"strings"
26+
"log"
27+
//"strconv"
28+
)
29+
30+
type FlasherError struct {
31+
err string
32+
}
33+
34+
func (e FlasherError) Error() string {
35+
return e.err
36+
}
37+
38+
type Flasher struct {
39+
port serial.Port
40+
}
41+
42+
func (flasher *Flasher) Hello() error {
43+
44+
f.Expect("ATE0", "OK", 100)
45+
f.Expect("ATE0", "OK", 100)
46+
f.Expect("ATE0", "OK", 100)
47+
_, err := flasher.Expect("AT", "OK", 100);
48+
return err
49+
}
50+
51+
func (flasher *Flasher) ExpectMinBytes(buffer string, response string, timeout int, min_bytes int) (string, error) {
52+
err := flasher.sendCommand([]byte(buffer + "\r\n"))
53+
if err != nil {
54+
return "", err
55+
}
56+
57+
log.Println("Sending " + buffer)
58+
59+
// Wait a bit
60+
// time.Sleep(time.Duration(timeout) * time.Millisecond)
61+
62+
// Receive response
63+
var res []byte
64+
n := 0
65+
66+
start := time.Now()
67+
68+
for ((time.Since(start) < time.Duration(timeout) * time.Millisecond && !strings.Contains(string(res), response)) || (len(res) < min_bytes)) {
69+
data := 0
70+
partial := make([]byte, 65535)
71+
data, err = flasher.port.Read(partial)
72+
res = append(res, partial[:data]...)
73+
n += data
74+
if err != nil {
75+
return "", err
76+
}
77+
}
78+
79+
log.Println(string(res))
80+
81+
if !strings.Contains(string(res), response) {
82+
return string(res), &FlasherError{err: "Expected " + response + ", got " + string(res)}
83+
}
84+
return string(res), nil
85+
}
86+
87+
func (flasher *Flasher) Expect(buffer string, response string, timeout int) (string, error) {
88+
return flasher.ExpectMinBytes(buffer, response, timeout, 0)
89+
}
90+
91+
func (flasher *Flasher) Close() error {
92+
return flasher.port.Close()
93+
}
94+
95+
func (flasher *Flasher) GetFwVersion() (string, error) {
96+
return flasher.ExpectMinBytes("ATI9", "05.06,A.02.", 100, 25)
97+
}
98+
99+
// Write a block of flash memory
100+
func (flasher *Flasher) Write(address uint32, buffer []byte) error {
101+
if err := flasher.sendCommand(buffer); err != nil {
102+
return err
103+
}
104+
return nil
105+
}
106+
107+
108+
// Fill buffer with data coming from serial port.
109+
// Blocks until the buffer is full.
110+
func (flasher *Flasher) serialFillBuffer(buffer []byte) error {
111+
read := 0
112+
for read < len(buffer) {
113+
n, err := flasher.port.Read(buffer[read:])
114+
if err != nil {
115+
return err
116+
}
117+
if n == 0 {
118+
return &FlasherError{err: "Serial port closed unexpectedly"}
119+
}
120+
read += n
121+
}
122+
return nil
123+
}
124+
125+
func (flasher *Flasher) sendCommand(payload []byte) error {
126+
if payload != nil {
127+
if _, err := flasher.port.Write(payload); err != nil {
128+
return err
129+
}
130+
}
131+
return nil
132+
}
133+
134+
func OpenSerial(portName string) (serial.Port, error) {
135+
mode := &serial.Mode{
136+
BaudRate: 1000000,
137+
Vtimeout: 100,
138+
Vmin: 0,
139+
}
140+
141+
return serial.Open(portName, mode)
142+
}
143+
144+
func OpenFlasher(portName string) (*Flasher, error) {
145+
146+
port, err := OpenSerial(portName)
147+
if err != nil {
148+
return nil, &FlasherError{err: "Error opening serial port. " + err.Error()}
149+
}
150+
151+
flasher := &Flasher{
152+
port: port,
153+
}
154+
155+
return flasher, err
156+
}
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*
2+
FirmwareUploader.go - A firmware uploader for the WiFi101 module.
3+
Copyright (c) 2015 Arduino LLC. All right reserved.
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package sara
21+
22+
import (
23+
"fmt"
24+
"github.com/arduino-libraries/WiFi101-FirmwareUpdater/bossac"
25+
"github.com/arduino-libraries/WiFi101-FirmwareUpdater/context"
26+
"io/ioutil"
27+
"log"
28+
"strconv"
29+
"time"
30+
)
31+
32+
var f *Flasher
33+
var payloadSize uint16
34+
var programmer context.Programmer
35+
36+
func Run(ctx context.Context) {
37+
38+
var err error
39+
programmer = &bossac.Bossac{}
40+
41+
if ctx.FWUploaderBinary != "" {
42+
log.Println("Flashing firmware uploader")
43+
if ctx.BinaryToRestore == "" {
44+
ctx.BinaryToRestore, err = programmer.DumpAndFlash(&ctx, ctx.FWUploaderBinary)
45+
} else {
46+
err = programmer.Flash(&ctx, ctx.FWUploaderBinary)
47+
}
48+
if err != nil {
49+
log.Fatal(err)
50+
}
51+
}
52+
53+
log.Println("Connecting to programmer")
54+
if _f, err := OpenFlasher(ctx.PortName); err != nil {
55+
log.Fatal(err)
56+
} else {
57+
f = _f
58+
}
59+
defer f.Close()
60+
61+
time.Sleep(2 * time.Second)
62+
63+
// Synchronize with programmer
64+
log.Println("Sync with programmer")
65+
if err := f.Hello(); err != nil {
66+
log.Fatal(err)
67+
}
68+
69+
// Check maximum supported payload size
70+
log.Println("Reading actual firmware version")
71+
fwVersion, err := f.GetFwVersion()
72+
if err != nil {
73+
log.Fatal(err)
74+
} else {
75+
payloadSize = 128
76+
}
77+
78+
log.Println("Initial firmware version: " + fwVersion)
79+
80+
if ctx.FirmwareFile != "" {
81+
if err := flashFirmware(ctx); err != nil {
82+
log.Fatal(err)
83+
}
84+
}
85+
86+
fwVersion, err = f.GetFwVersion()
87+
if err != nil {
88+
log.Fatal(err)
89+
}
90+
91+
log.Println("After applying update firmware version: " + fwVersion)
92+
93+
if ctx.BinaryToRestore != "" {
94+
log.Println("Restoring previous sketch")
95+
f.Close()
96+
97+
if err := programmer.Flash(&ctx, ctx.BinaryToRestore); err != nil {
98+
log.Fatal(err)
99+
}
100+
101+
// just to allow cleanup via defer()
102+
// f.port, _ = OpenSerial(ctx.PortName)
103+
}
104+
}
105+
106+
func flashFirmware(ctx context.Context) error {
107+
FirmwareOffset := 0x0000
108+
109+
log.Printf("Flashing firmware from '%v'", ctx.FirmwareFile)
110+
111+
fwData, err := ioutil.ReadFile(ctx.FirmwareFile)
112+
if err != nil {
113+
return err
114+
}
115+
116+
_, err = f.Expect("AT+ULSTFILE", "+ULSTFILE:", 1000)
117+
if err != nil {
118+
return err
119+
}
120+
121+
_, err = f.Expect("AT+UDWNFILE=\"UPDATE.BIN\"," + strconv.Itoa(len(fwData)) + ",\"FOAT\"", ">", 20000)
122+
if err != nil {
123+
return err
124+
}
125+
126+
err = flashChunk(FirmwareOffset, fwData)
127+
if err != nil {
128+
return err
129+
}
130+
131+
time.Sleep(1 * time.Second)
132+
133+
_, err = f.Expect("", "OK", 1000)
134+
if err != nil {
135+
return err
136+
}
137+
138+
_, err = f.Expect("AT+UFWINSTALL", "OK", 60000)
139+
if err != nil {
140+
return err
141+
}
142+
143+
time.Sleep(10 * time.Second)
144+
145+
// wait up to 20 minutes trying to ping the module. After 20 minutes signal the error
146+
start := time.Now()
147+
for (time.Since(start) < time.Minute * 20) {
148+
err = f.Hello()
149+
if (err == nil) {
150+
return nil
151+
}
152+
time.Sleep(1 * time.Second)
153+
}
154+
return err
155+
}
156+
157+
func flashChunk(offset int, buffer []byte) error {
158+
chunkSize := int(payloadSize)
159+
bufferLength := len(buffer)
160+
161+
for i := 0; i < bufferLength; i += chunkSize {
162+
fmt.Printf("\rFlashing: " + strconv.Itoa((i*100)/bufferLength) + "%%")
163+
start := i
164+
end := i + chunkSize
165+
if end > bufferLength {
166+
end = bufferLength
167+
}
168+
if err := f.Write(uint32(offset+i), buffer[start:end]); err != nil {
169+
return err
170+
}
171+
//time.Sleep(1 * time.Millisecond)
172+
}
173+
174+
return nil
175+
}

0 commit comments

Comments
 (0)