# stm32flash - has anyone got a working version?



## tingo (Aug 18, 2013)

I compiled stm32flash under FreeBSD 8.4-STABLE:

```
tingo@kg-core1$ uname -a
FreeBSD kg-core1.kg4.no 8.4-STABLE FreeBSD 8.4-STABLE #0 r253646: Thu Jul 25 10:12:31 UTC 2013
     root@kg-core1.kg4.no:/usr/obj/usr/src/sys/GENERIC  amd64
```
I just unpacked the source code and compiled it, no patches:

```
tingo@kg-core1$ pwd
/home/tingo/work/stm32flash
tingo@kg-core1$ gmake
gmake -C parsers
gmake[1]: Entering directory `/zs/tingo/work/stm32flash/parsers'
gcc -g -Wall -c -I../ binary.c hex.c
ar r parsers.a        binary.o hex.o
ar: warning: creating parsers.a
gmake[1]: Leaving directory `/zs/tingo/work/stm32flash/parsers'
gcc -g -o stm32flash -I./ \
    main.c \
    utils.c \
    stm32.c \
    serial_common.c \
    serial_platform.c \
    parsers/parsers.a \
    stm32/stmreset_binary.c \
    -Wall
In file included from main.c:31:
serial.h:82: warning: type qualifiers ignored on function return type
serial.h:83: warning: type qualifiers ignored on function return type
serial.h:84: warning: type qualifiers ignored on function return type
serial.h:85: warning: type qualifiers ignored on function return type
In file included from stm32.h:25,
                 from stm32.c:24:
serial.h:82: warning: type qualifiers ignored on function return type
serial.h:83: warning: type qualifiers ignored on function return type
serial.h:84: warning: type qualifiers ignored on function return type
serial.h:85: warning: type qualifiers ignored on function return type
In file included from serial_common.c:20:
serial.h:82: warning: type qualifiers ignored on function return type
serial.h:83: warning: type qualifiers ignored on function return type
serial.h:84: warning: type qualifiers ignored on function return type
serial.h:85: warning: type qualifiers ignored on function return type
serial_common.c:39: warning: type qualifiers ignored on function return type
serial_common.c:57: warning: type qualifiers ignored on function return type
serial_common.c:69: warning: type qualifiers ignored on function return type
serial_common.c:80: warning: type qualifiers ignored on function return type
In file included from serial_posix.c:28,
                 from serial_platform.c:4:
serial.h:82: warning: type qualifiers ignored on function return type
serial.h:83: warning: type qualifiers ignored on function return type
serial.h:84: warning: type qualifiers ignored on function return type
serial.h:85: warning: type qualifiers ignored on function return type
```
The resulting binary appears to work:

```
tingo@kg-core1$ ./stm32flash
stm32flash - http://stm32flash.googlecode.com/

ERROR: Device not specified
Usage: ./stm32flash [-bvngfhc] [-[rw] filename] /dev/ttyS0
    -b rate        Baud rate (default 57600)
    -r filename    Read flash to file
    -w filename    Write flash to file
    -u        Disable the flash write-protection
    -e n        Only erase n pages before writing the flash
    -v        Verify writes
    -n count    Retry failed writes up to count times (default 10)
    -g address    Start execution at specified address (0 = flash start)
    -f        Force binary parser
    -h        Show this help
    -c        Resume the connection (don't send initial INIT)
            *Baud rate must be kept the same as the first init*
            This is useful if the reset fails

Examples:
    Get device information:
        ./stm32flash /dev/ttyS0

    Write with verify and then start execution:
        ./stm32flash -w filename -v -g 0x0 /dev/ttyS0

    Read flash to file:
        ./stm32flash -r filename /dev/ttyS0

    Start execution:
        ./stm32flash -g 0x0 /dev/ttyS0
```
I have an STM32 board connected to cuaU0/ttyU0:

```
tingo@kg-core1$ ls -l /dev/cuaU* /dev/ttyU*
crw-rw----  1 uucp  operator    0, 159 Aug 18 17:26 /dev/cuaU0
crw-rw----  1 uucp  operator    0, 160 Aug 18 17:26 /dev/cuaU0.init
crw-rw----  1 uucp  operator    0, 161 Aug 18 17:26 /dev/cuaU0.lock
crw-rw----  1 root  operator    0, 156 Aug 18 17:26 /dev/ttyU0
crw-rw----  1 root  operator    0, 157 Aug 18 17:26 /dev/ttyU0.init
crw-rw----  1 root  operator    0, 158 Aug 18 17:26 /dev/ttyU0.lock
```
and my user has access:

```
tingo@kg-core1$ id
uid=1001(tingo) gid=1001(users) groups=1001(users),0(wheel),5(operator)
```
Still it doesn't work:

```
tingo@kg-core1$ ./stm32flash /dev/cuaU0
stm32flash - http://stm32flash.googlecode.com/

/dev/cuaU0: No such file or directory
tingo@kg-core1$ ./stm32flash /dev/ttyU0
stm32flash - http://stm32flash.googlecode.com/

/dev/ttyU0: No such file or directory
```
It doesn't work as root either, so it doesn't look like a permissions problem.

BTW, stm32flash with the same board and cable works nicely under Linux. Any hints on what could be wrong?


----------



## tingo (Sep 17, 2013)

Nobody doing embedded ARM programming under FreeBSD?


----------



## wblock@ (Sep 17, 2013)

They are probably mostly on the freebsd-embedded or freebsd-arm mailing lists.


----------



## tingo (Sep 18, 2013)

Indeed they do. First advice is to run truss(1) on the command, like this:

```
tingo@kg-core1$ truss ./stm32flash /dev/cuaU0
__sysctl(0x7fffffffe070,0x2,0x7fffffffe08c,0x7fffffffe080,0x0,0x0) = 0 (0x0)
mmap(0x0,688,PROT_READ|PROT_WRITE,MAP_ANON,-1,0x0) = 34365198336 (0x800535000)
munmap(0x800535000,688)                 = 0 (0x0)
__sysctl(0x7fffffffe0e0,0x2,0x80063f408,0x7fffffffe0d8,0x0,0x0) = 0 (0x0)
mmap(0x0,32768,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34365198336 (0x800535000)
issetugid(0x800536015,0x800530684,0x80064bb10,0x80064bae0,0x5991,0x0) = 0 (0x0)
open("/etc/libmap.conf",O_RDONLY,0666)         ERR#2 'No such file or directory'
open("/var/run/ld-elf.so.hints",O_RDONLY,057)     = 3 (0x3)
read(3,"Ehnt\^A\0\0\0\M^@\0\0\0002\^A\0"...,128) = 128 (0x80)
lseek(3,0x80,SEEK_SET)                 = 128 (0x80)
read(3,"/lib:/usr/lib:/usr/lib/compat:/u"...,306) = 306 (0x132)
close(3)                     = 0 (0x0)
access("/lib/libc.so.7",0)             = 0 (0x0)
open("/lib/libc.so.7",O_RDONLY,030771340)     = 3 (0x3)
fstat(3,{ mode=-r--r--r-- ,inode=5537727,size=1298464,blksize=32768 }) = 0 (0x0)
pread(0x3,0x80063e2c0,0x1000,0x0,0x101010101010101,0x8080808080808080) = 4096 (0x1000)
mmap(0x0,2371584,PROT_NONE,MAP_PRIVATE|MAP_ANON|MAP_NOCORE,-1,0x0)
 = 34366341120 (0x80064c000)
mmap(0x80064c000,1085440,PROT_READ|PROT_EXEC,MAP_PRIVATE|MAP_FIXED|MAP_NOCORE,3,0x0)
 = 34366341120 (0x80064c000)
mmap(0x800855000,126976,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED,3,0x109000)
 = 34368475136 (0x800855000)
mmap(0x800874000,110592,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED|MAP_ANON,-1,0x0)
 = 34368602112 (0x800874000)
close(3)                     = 0 (0x0)
mmap(0x0,656,PROT_READ|PROT_WRITE,MAP_ANON,-1,0x0) = 34365231104 (0x80053d000)
munmap(0x80053d000,656)                 = 0 (0x0)
mmap(0x0,43904,PROT_READ|PROT_WRITE,MAP_ANON,-1,0x0) = 34365231104 (0x80053d000)
munmap(0x80053d000,43904)             = 0 (0x0)
sysarch(0x81,0x7fffffffe160,0x800539088,0x0,0xffffffffffcde450,0x8080808080808080) = 0 (0x0)
sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTERM|SIGURG|
SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|
SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0)
sigprocmask(SIG_SETMASK,0x0,0x0)         = 0 (0x0)
__sysctl(0x7fffffffe0f0,0x2,0x80087a780,0x7fffffffe0e8,0x0,0x0) = 0 (0x0)
sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTERM|SIGURG|
SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|
SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0)
sigprocmask(SIG_SETMASK,0x0,0x0)         = 0 (0x0)
fstat(1,{ mode=crw--w---- ,inode=147,size=0,blksize=4096 }) = 0 (0x0)
__sysctl(0x7fffffffe0b0,0x2,0x800879dc8,0x7fffffffe0a8,0x0,0x0) = 0 (0x0)
__sysctl(0x7fffffffdfd0,0x2,0x7fffffffdf60,0x7fffffffdfc8,0x8007478c0,0xc) = 0 (0x0)
__sysctl(0x7fffffffdf60,0x2,0x800879fd0,0x7fffffffe028,0x0,0x0) = 0 (0x0)
readlink("/etc/malloc.conf",0x7fffffffe0d0,1024) ERR#2 'No such file or directory'
issetugid(0x800746581,0x7fffffffe0d0,0xffffffffffffffff,0x0,0x2,0x0) = 0 (0x0)
break(0x600000)                     = 0 (0x0)
__sysctl(0x7fffffffe360,0x2,0x7fffffffe37c,0x7fffffffe370,0x0,0x0) = 0 (0x0)
mmap(0x0,2097152,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0)
 = 34368712704 (0x80088f000)
mmap(0x800a8f000,1511424,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0)
 = 34370809856 (0x800a8f000)
munmap(0x80088f000,1511424)             = 0 (0x0)
ioctl(1,TIOCGETA,0xffffe540)             = 0 (0x0)
stm32flash - http://stm32flash.googlecode.com/
write(1,"stm32flash - http://stm32flash.g"...,47) = 47 (0x2f)

write(1,"\n",1)                     = 1 (0x1)
open("/dev/cuaU0",O_RDWR|O_NONBLOCK|O_NOCTTY,00) = 3 (0x3)
fcntl(3,F_SETFL,0x0)                 = 0 (0x0)
ioctl(3,TIOCGETA,0xa07084)             = 0 (0x0)
ioctl(3,TIOCGETA,0xa070b0)             = 0 (0x0)
ioctl(3,TIOCFLUSH,0xffffe5c4)             = 0 (0x0)
ioctl(3,TIOCSETA,0xa070b0)             = 0 (0x0)
ioctl(3,TIOCGETA,0xffffe620)             = 0 (0x0)
stat("/usr/share/nls/C/libc.cat",0x7fffffffd8b0) ERR#2 'No such file or directory'
stat("/usr/share/nls/libc/C",0x7fffffffd8b0)     ERR#2 'No such file or directory'
stat("/usr/local/share/nls/C/libc.cat",0x7fffffffd8b0) ERR#2 'No such file or directory'
stat("/usr/local/share/nls/libc/C",0x7fffffffd8b0) ERR#2 'No such file or directory'
/dev/cuaU0: No such file or directory
writev(0x2,0x7fffffffddf0,0x4,0x19,0x1b4664,0x800a00128) = 38 (0x26)
ioctl(3,TIOCFLUSH,0xffffe624)             = 0 (0x0)
ioctl(3,TIOCSETA,0xa07084)             = 0 (0x0)
close(3)                     = 0 (0x0)

write(1,"\n",1)                     = 1 (0x1)
sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|
SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|
SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0)
sigprocmask(SIG_SETMASK,0x0,0x0)         = 0 (0x0)
sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|
SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|
SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0)
sigprocmask(SIG_SETMASK,0x0,0x0)         = 0 (0x0)
process exit, rval = 1
```
Hopefully someone sees something not normal here.


----------



## wblock@ (Sep 18, 2013)

Right after it tries to open a bunch of NLS stuff, it says that the serial port does not exist.  Can you build it without NLS?


----------



## tingo (Sep 26, 2013)

I don't think I can build it without NLS, the program just uses perror(). However, somebody has already figured out that the problem is in the serial_setup() function (in serial_posix.c); the code does a tcsetattr() followed by a tcgetattr(), and if the values returned by the tcgetattr() doesn't match the ones given as argument to the tcsetattr(), the code just returns with, in effect "serial port does not exist". Not very elegant, but I haven't had time to fix it.


----------



## tingo (Sep 27, 2013)

Ok, I had a look at it today, and it was a problem with termios flags in the serial routines (serial_posix.c). Part of the code for the serial_setup() function is:

```
switch(parity) {
		case SERIAL_PARITY_NONE: port_parity = 0;                       break;
		case SERIAL_PARITY_EVEN: port_parity = INPCK | PARENB;          break;
		case SERIAL_PARITY_ODD : port_parity = INPCK | PARENB | PARODD; break;

		default:
			return SERIAL_ERR_INVALID_PARITY;
	}
```
which later gets stuffed into control flags:

```
h->newtio.c_cflag |=
		port_parity	|
		port_bits	|
		port_stop	|
		CLOCAL		|
		CREAD;
```
The only problem with that is that *INPCK* is an input flag (on FreeBSD at last, haven't checked Linux), so when the code later compares the control flags sent to tcsetattr with the ones read from tcgetattr, they differ. And since the checking part looks like this:

```
if (
		settings.c_iflag != h->newtio.c_iflag ||
		settings.c_oflag != h->newtio.c_oflag ||
		settings.c_cflag != h->newtio.c_cflag ||
		settings.c_lflag != h->newtio.c_lflag
	)	return SERIAL_ERR_UNKNOWN;
```
we get the "no such file" error. Simply removing *INPCK* from the code above and recompiling gives me (you have to put the board in the correct mode first, by holding down the BOOT0 button while pressing the RESET button):

```
tingo@kg-core1$ ./stm32flash /dev/cuaU0
stm32flash - http://stm32flash.googlecode.com/

Serial Config: 57600 8E1
Version      : 0x22
Option 1     : 0x00
Option 2     : 0x00
Device ID    : 0x0410 (Medium-density)
RAM          : 20KiB  (512b reserved by bootloader)
Flash        : 128KiB (sector size: 4x1024)
Option RAM   : 15b
System RAM   : 2KiB

Resetting device... done.
```
So now it works.


----------

