@@ -62,6 +62,7 @@ unsigned char imagebuf[IMAGEBUFSIZE + 1];
6262#define MODE " M"
6363#define FORMAT " format "
6464#define VERSION "Firmware version: "
65+ #define BOOTVERSION "BuildHAT bootloader"
6566#define DONEINIT "Done initialising ports"
6667
6768#define BASE_DIRECTORY "/sys/class/gpio"
@@ -745,9 +746,9 @@ int load_firmware(char *firmware_path, char *signature_path)
745746 return -1 ;
746747}
747748
748-
749- long checkversion (){
750- char vbuf [ 100 ] ;
749+ char * checkmessage ( char * message , char * send ){
750+ int buffsize = 100 ;
751+ char * vbuf = malloc ( buffsize ) ;
751752 char * vbuf_t = vbuf ;
752753 int nfds ;
753754 struct epoll_event ev1 , events [1 ];
@@ -766,6 +767,13 @@ long checkversion(){
766767 exit (EXIT_FAILURE );
767768 }
768769
770+ if (write (uart_fd , send , strlen (send )) != strlen (send )){
771+ // Failed to write data
772+ goto cleanup ;
773+ }
774+
775+ int diffcount = 0 ;
776+
769777 while (1 ){
770778 nfds = epoll_wait (epollfd , events , MAX_EVENTS , 2000 );
771779 if (nfds == -1 ) {
@@ -774,39 +782,49 @@ long checkversion(){
774782 }
775783 if (nfds == 0 ){
776784 // No data
777- return 0 ;
785+ goto cleanup ;
778786 }
779787 for (int n = 0 ; n < nfds ; ++ n ) {
780788 if ( events [n ].data .fd == uart_fd ){
781789 int rcount = read (events [n ].data .fd , vbuf_t , 1 );
782790 if (rcount == 1 ){
783791 if (vbuf_t [0 ] == '\n' ){
784- if (strncmp (VERSION , vbuf , strlen (VERSION )) == 0 ) {
785- return strtol (vbuf + strlen (VERSION ), NULL , 10 );
792+ vbuf_t [0 ] = 0 ;
793+ if (strncmp (message , vbuf , strlen (message )) == 0 ) {
794+ return vbuf ;
795+ } else {
796+ // Different message than expected
797+ diffcount ++ ;
798+ if (diffcount >= 2 )
799+ goto cleanup ;
786800 }
787801 vbuf_t = vbuf ;
788802 break ;
789803 }
790804 vbuf_t ++ ;
791- if ((vbuf_t - vbuf ) >= sizeof vbuf )
792- vbuf_t = 0 ;
805+ if ((vbuf_t - vbuf ) >= buffsize ){
806+ vbuf_t = vbuf ;
807+ }
793808 } else {
794809 // No data
795- return 0 ;
810+ goto cleanup ;
796811 }
797812 }
798813 }
799814 }
800- return 0 ;
815+
816+ cleanup :
817+ epoll_ctl (epollfd , EPOLL_CTL_DEL , uart_fd , & ev1 );
818+ return NULL ;
801819}
802820
821+
803822/* Open the UART bus, select the Hat as the device to communicate with,
804823 * and return the file descriptor. You must close the file descriptor
805824 * when you are done with it.
806825 */
807826int uart_open_hat (char * firmware_path , char * signature_path , long version )
808827{
809- char * buffer = "version\r" ;
810828 enum hatstate state = other ;
811829 int rv ;
812830 struct termios ttyopt ;
@@ -833,34 +851,31 @@ int uart_open_hat(char *firmware_path, char *signature_path, long version)
833851 tcsetattr (uart_fd , TCSANOW , & ttyopt );
834852 tcflush (uart_fd , TCIOFLUSH );
835853
836- if (getprompt () ){
854+ if (checkmessage ( BOOTVERSION , "version\r" ) != NULL ){
837855 state = bootloader ;
838856 if (load_firmware (firmware_path , signature_path ) < 0 ){
839857 PyErr_SetString (PyExc_IOError , "Failed to load firmware" );
840858 close (uart_fd );
841859 return -1 ;
842860 }
843861 } else {
844- long ver = 0 ;
845862
846- if (write (uart_fd , buffer , strlen ((char * )buffer )) < 0 ){
847- PyErr_SetString (PyExc_IOError , "Failed to send command" );
848- close (uart_fd );
849- return -1 ;
863+ long ver = 0 ;
864+ char * vers = checkmessage (VERSION ,"version\r" );
865+ if (vers != NULL ){
866+ ver = strtol (vers + strlen (VERSION ), NULL , 10 );
867+ if (ver > 0 )
868+ state = firmware ;
850869 }
851870
852- ver = checkversion ();
853- if (ver > 0 )
854- state = firmware ;
855-
856871 if (state == firmware ){
857872 if (ver != version ){
858873 if (uart_reset_hat () < 0 ){
859874 PyErr_SetString (PyExc_IOError , "Failed to reset hat for new firmware" );
860875 close (uart_fd );
861876 return -1 ;
862877 }
863- if (getprompt () ){
878+ if (checkmessage ( BOOTVERSION , "version\r" ) != NULL ){
864879 state = bootloader ;
865880 if (load_firmware (firmware_path , signature_path ) < 0 ){
866881 PyErr_SetString (PyExc_IOError , "Failed to load new firmware" );
@@ -934,8 +949,11 @@ int uart_open_hat(char *firmware_path, char *signature_path, long version)
934949 sleep (7 );
935950 } else if (state == firmware ){
936951 // Already in current firmware, so just list devices that are connected
937- char * buffer = "list\r" ;
952+ char * buffer = "echo 0; list\r" ;
938953 if (write (uart_fd , buffer , strlen ((char * )buffer )) < 0 ){
954+ PyErr_SetString (PyExc_IOError , "Failed to list devices" );
955+ close (uart_fd );
956+ return -1 ;
939957 }
940958 }
941959
0 commit comments