Skip to content

Commit 6b7422a

Browse files
committed
Initial version from Bogdan Marinescu.
0 parents  commit 6b7422a

7 files changed

+799
-0
lines changed

main.c

+147
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Loader driver
2+
3+
#include "stm32ld.h"
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
#include <errno.h>
7+
#include <limits.h>
8+
9+
static FILE *fp;
10+
static u32 fpsize;
11+
12+
#define BL_VERSION_MAJOR 2
13+
#define BL_VERSION_MINOR 1
14+
#define CHIP_ID 0x0414
15+
16+
// ****************************************************************************
17+
// Helper functions and macros
18+
19+
// Get data function
20+
static u32 writeh_read_data( u8 *dst, u32 len )
21+
{
22+
size_t readbytes = 0;
23+
24+
if( !feof( fp ) )
25+
readbytes = fread( dst, 1, len, fp );
26+
return ( u32 )readbytes;
27+
}
28+
29+
// Progress function
30+
static void writeh_progress( u32 wrote )
31+
{
32+
unsigned pwrite = ( wrote * 100 ) / fpsize;
33+
static int expected_next = 10;
34+
35+
if( pwrite >= expected_next )
36+
{
37+
printf( "%d%% ", expected_next );
38+
expected_next += 10;
39+
}
40+
}
41+
42+
// ****************************************************************************
43+
// Entry point
44+
45+
int main( int argc, const char **argv )
46+
{
47+
u8 minor, major;
48+
u16 version;
49+
long baud;
50+
51+
// Argument validation
52+
if( argc != 4 )
53+
{
54+
fprintf( stderr, "Usage: stm32ld <port> <baud> <binary image name>\n" );
55+
exit( 1 );
56+
}
57+
errno = 0;
58+
baud = strtol( argv[ 2 ], NULL, 10 );
59+
if( ( errno == ERANGE && ( baud == LONG_MAX || baud == LONG_MIN ) ) || ( errno != 0 && baud == 0 ) || ( baud < 0 ) )
60+
{
61+
fprintf( stderr, "Invalid baud '%s'\n", argv[ 2 ] );
62+
exit( 1 );
63+
}
64+
if( ( fp = fopen( argv[ 3 ], "rb" ) ) == NULL )
65+
{
66+
fprintf( stderr, "Unable to open %s\n", argv[ 3 ] );
67+
exit( 1 );
68+
}
69+
else
70+
{
71+
fseek( fp, 0, SEEK_END );
72+
fpsize = ftell( fp );
73+
fseek( fp, 0, SEEK_SET );
74+
}
75+
76+
// Connect to bootloader
77+
if( stm32_init( argv[ 1 ], baud ) != STM32_OK )
78+
{
79+
fprintf( stderr, "Unable to connect to bootloader\n" );
80+
exit( 1 );
81+
}
82+
83+
// Get version
84+
if( stm32_get_version( &major, &minor ) != STM32_OK )
85+
{
86+
fprintf( stderr, "Unable to get bootloader version\n" );
87+
exit( 1 );
88+
}
89+
else
90+
{
91+
printf( "Found bootloader version: %d.%d\n", major, minor );
92+
if( major != BL_VERSION_MAJOR || minor != BL_VERSION_MINOR )
93+
{
94+
fprintf( stderr, "Unsupported bootloader version" );
95+
exit( 1 );
96+
}
97+
}
98+
99+
// Get chip ID
100+
if( stm32_get_chip_id( &version ) != STM32_OK )
101+
{
102+
fprintf( stderr, "Unable to get chip ID\n" );
103+
exit( 1 );
104+
}
105+
else
106+
{
107+
printf( "Chip ID: %04X\n", version );
108+
if( version != CHIP_ID )
109+
{
110+
fprintf( stderr, "Unsupported chip ID" );
111+
exit( 1 );
112+
}
113+
}
114+
115+
// Write unprotect
116+
if( stm32_write_unprotect() != STM32_OK )
117+
{
118+
fprintf( stderr, "Unable to execute write unprotect\n" );
119+
exit( 1 );
120+
}
121+
else
122+
printf( "Cleared write protection.\n" );
123+
124+
// Erase flash
125+
if( stm32_erase_flash() != STM32_OK )
126+
{
127+
fprintf( stderr, "Unable to erase chip\n" );
128+
exit( 1 );
129+
}
130+
else
131+
printf( "Erased FLASH memory.\n" );
132+
133+
// Program flash
134+
setbuf( stdout, NULL );
135+
printf( "Programming flash ... ");
136+
if( stm32_write_flash( writeh_read_data, writeh_progress ) != STM32_OK )
137+
{
138+
fprintf( stderr, "Uanble to program FLASH memory.\n" );
139+
exit( 1 );
140+
}
141+
else
142+
printf( "\nDone.\n" );
143+
144+
fclose( fp );
145+
return 0;
146+
}
147+

serial.h

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// STM32 loader serial interface
2+
3+
#ifndef __SERIAL_H__
4+
#define __SERIAL_H__
5+
6+
#include "type.h"
7+
8+
#define SER_INF_TIMEOUT 0xFFFFFFFF
9+
#define SER_NO_TIMEOUT 0
10+
#define SER_OK 0
11+
#define SER_ERR 1
12+
13+
// Serial interface modes (blocking or non blocking)
14+
#define SER_MODE_BLOCKING 0
15+
#define SER_MODE_NONBLOCKING 1
16+
17+
// Setup constants
18+
#define SER_PARITY_NONE 0
19+
#define SER_PARITY_EVEN 1
20+
#define SER_PARITY_ODD 2
21+
22+
#define SER_STOPBITS_1 0
23+
#define SER_STOPBITS_1_5 1
24+
#define SER_STOPBITS_2 2
25+
26+
#define SER_DATABITS_5 5
27+
#define SER_DATABITS_6 6
28+
#define SER_DATABITS_7 7
29+
#define SER_DATABITS_8 8
30+
31+
// Serial access functions (to be implemented by each platform)
32+
ser_handler ser_open( const char *sername );
33+
void ser_close( ser_handler id );
34+
int ser_setup( ser_handler id, u32 baud, int databits, int parity, int stopbits );
35+
u32 ser_read( ser_handler id, u8* dest, u32 maxsize );
36+
int ser_read_byte( ser_handler id );
37+
u32 ser_write( ser_handler id, const u8 *src, u32 size );
38+
u32 ser_write_byte( ser_handler id, u8 data );
39+
void ser_set_timeout_ms( ser_handler id, u32 timeout );
40+
41+
#endif

serial_posix.c

+184
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
// Serial inteface implementation for POSIX-compliant systems
2+
3+
#include "serial.h"
4+
#include <stdio.h>
5+
#include <string.h>
6+
#include <unistd.h>
7+
#include <fcntl.h>
8+
#include <errno.h>
9+
#include <termios.h>
10+
#include <sys/select.h>
11+
#include <sys/time.h>
12+
#include <sys/types.h>
13+
14+
static u32 ser_timeout = SER_INF_TIMEOUT;
15+
16+
// Open the serial port
17+
ser_handler ser_open( const char* sername )
18+
{
19+
int fd;
20+
21+
if( ( fd = open( sername, O_RDWR | O_NOCTTY | O_NDELAY ) ) == -1 )
22+
perror( "ser_open: unable to open port" );
23+
else
24+
fcntl( fd, F_SETFL, 0 );
25+
return ( ser_handler )fd;
26+
}
27+
28+
// Close the serial port
29+
void ser_close( ser_handler id )
30+
{
31+
close( ( int )id );
32+
}
33+
34+
// Helper function: get baud ID from actual baud rate
35+
#define BAUDCASE(x) case x: return B##x
36+
static u32 ser_baud_to_id( u32 baud )
37+
{
38+
switch( baud )
39+
{
40+
BAUDCASE( 1200 );
41+
BAUDCASE( 1800 );
42+
BAUDCASE( 2400 );
43+
BAUDCASE( 4800 );
44+
BAUDCASE( 9600 );
45+
BAUDCASE( 19200 );
46+
BAUDCASE( 38400 );
47+
BAUDCASE( 57600 );
48+
BAUDCASE( 115200 );
49+
BAUDCASE( 230400 );
50+
}
51+
return 0;
52+
}
53+
54+
// Helper function: get number of bits ID from actual number of bits
55+
#define NBCASE(x) case x: return CS##x
56+
static int ser_number_of_bits_to_id( int nb )
57+
{
58+
switch( nb )
59+
{
60+
NBCASE( 5 );
61+
NBCASE( 6 );
62+
NBCASE( 7 );
63+
NBCASE( 8 );
64+
}
65+
return 0;
66+
}
67+
68+
int ser_setup( ser_handler id, u32 baud, int databits, int parity, int stopbits )
69+
{
70+
struct termios termdata;
71+
int hnd = ( int )id;
72+
73+
usleep( 200000 );
74+
tcgetattr( hnd, &termdata );
75+
76+
// Baud rate
77+
cfsetispeed( &termdata, ser_baud_to_id( baud ) );
78+
cfsetospeed( &termdata, ser_baud_to_id( baud ) );
79+
80+
// Parity / stop bits
81+
termdata.c_cflag &= ~CSTOPB;
82+
if( parity == SER_PARITY_NONE ) // no parity
83+
{
84+
termdata.c_cflag &= ~PARENB;
85+
}
86+
else if( parity == SER_PARITY_EVEN ) // even parity
87+
{
88+
termdata.c_cflag |= PARENB;
89+
termdata.c_cflag &= ~PARODD;
90+
}
91+
else if( parity == SER_PARITY_ODD ) // odd parity
92+
{
93+
termdata.c_cflag |= PARENB;
94+
termdata.c_cflag |= PARODD;
95+
}
96+
97+
// Data bits
98+
termdata.c_cflag |= ( CLOCAL | CREAD );
99+
termdata.c_cflag &= ~CSIZE;
100+
termdata.c_cflag |= ser_number_of_bits_to_id( databits );
101+
102+
// Disable HW and SW flow control
103+
termdata.c_cflag &= ~CRTSCTS;
104+
termdata.c_iflag &= ~( IXON | IXOFF | IXANY );
105+
106+
// Raw input
107+
termdata.c_lflag &= ~( ICANON | ECHO | ECHOE | ISIG );
108+
109+
// Raw output
110+
termdata.c_oflag &= ~OPOST;
111+
112+
// Check and strip parity bit
113+
if( parity == SER_PARITY_NONE )
114+
termdata.c_iflag &= ~( INPCK | ISTRIP );
115+
else
116+
termdata.c_iflag |= ( INPCK | ISTRIP );
117+
118+
// Setup timeouts
119+
termdata.c_cc[ VMIN ] = 1;
120+
termdata.c_cc[ VTIME ] = 0;
121+
122+
// Set the attibutes now
123+
tcsetattr( hnd, TCSANOW, &termdata );
124+
125+
// Flush everything
126+
tcflush( hnd, TCIOFLUSH );
127+
128+
// And set blocking mode by default
129+
fcntl( id, F_SETFL, 0 );
130+
}
131+
132+
// Read up to the specified number of bytes, return bytes actually read
133+
u32 ser_read( ser_handler id, u8* dest, u32 maxsize )
134+
{
135+
if( ser_timeout == SER_INF_TIMEOUT )
136+
return ( u32 )read( ( int )id, dest, maxsize );
137+
else
138+
{
139+
fd_set readfs;
140+
struct timeval tv;
141+
int retval;
142+
143+
FD_ZERO( &readfs );
144+
FD_SET( ( int )id, &readfs );
145+
tv.tv_sec = ser_timeout / 1000000;
146+
tv.tv_usec = ( ser_timeout % 1000000 ) * 1000;
147+
retval = select( ( int )id + 1, &readfs, NULL, NULL, &tv );
148+
if( retval == -1 || retval == 0 )
149+
return 0;
150+
else
151+
return ( u32 )read( ( int )id, dest, maxsize );
152+
}
153+
}
154+
155+
// Read a single byte and return it (or -1 for error)
156+
int ser_read_byte( ser_handler id )
157+
{
158+
u8 data;
159+
int res = ser_read( id, &data, 1 );
160+
161+
return res == 1 ? data : -1;
162+
}
163+
164+
// Write up to the specified number of bytes, return bytes actually written
165+
u32 ser_write( ser_handler id, const u8 *src, u32 size )
166+
{
167+
u32 res;
168+
169+
res = ( u32 )write( ( int )id, src, size );
170+
return res;
171+
}
172+
173+
// Write a byte to the serial port
174+
u32 ser_write_byte( ser_handler id, u8 data )
175+
{
176+
return ( u32 )write( id, &data, 1 );
177+
}
178+
179+
// Set communication timeout
180+
void ser_set_timeout_ms( ser_handler id, u32 timeout )
181+
{
182+
ser_timeout = timeout;
183+
}
184+

0 commit comments

Comments
 (0)