diff options
| -rw-r--r-- | busdevice.c | 5 | ||||
| -rw-r--r-- | devicedeployment.c | 60 | ||||
| -rw-r--r-- | devicedeployment.h | 10 | ||||
| -rw-r--r-- | pcserialport.c | 87 | ||||
| -rw-r--r-- | simplemotion_defs.h | 2 | ||||
| -rw-r--r-- | tcpclient.c | 12 |
6 files changed, 125 insertions, 51 deletions
diff --git a/busdevice.c b/busdevice.c index b73da3f..4bc0ee0 100644 --- a/busdevice.c +++ b/busdevice.c @@ -137,6 +137,7 @@ static int parseIpAddress(const char *s, char *ip, size_t ipsize, short *port) { const char *ip_end, *port_start; + //ip_end and port_start are pointers to memory area of s, not offsets or indexes to s if (validateIpAddress(s, &ip_end, &port_start) == -1) return -1; @@ -144,7 +145,7 @@ static int parseIpAddress(const char *s, char *ip, size_t ipsize, short *port) if (!ip) return 0; - if (ipsize < ip_end - s + 1) + if (ipsize < (size_t)(ip_end - s + 1)) return -1; memcpy(ip, s, ip_end - s); @@ -182,7 +183,7 @@ smbusdevicehandle smBDOpen( const char *devicename ) //all handles in use if(handle>=SM_MAX_BUSES) return -1; - if(strncmp(devicename,"COM",3) == 0 || strncmp(devicename,"/dev/tty",8) == 0) //use rs232 lib + if(strncmp(devicename,"COM",3) == 0 || strncmp(devicename,"/dev/tty",8) == 0 || strncmp(devicename,"/dev/cu.",8) == 0) //use rs232 lib { BusDevice[handle].comPort=serialPortOpen( devicename, SMBusBaudrate ); if( BusDevice[handle].comPort == -1 ) diff --git a/devicedeployment.c b/devicedeployment.c index fbf909a..c832575 100644 --- a/devicedeployment.c +++ b/devicedeployment.c @@ -36,7 +36,7 @@ unsigned int readFileLine( const smuint8 *data, const int dataLen, int *readPosi char c; do { - if(*readPosition>=dataLen)//end of data buffer + if((*readPosition)>=dataLen)//end of data buffer { *eof=smtrue; c=0; @@ -44,12 +44,12 @@ unsigned int readFileLine( const smuint8 *data, const int dataLen, int *readPosi else { *eof=smfalse; - c=data[*readPosition+len]; + c=data[(*readPosition)]; (*readPosition)++; } //eol or eof - if( *eof==smtrue || c=='\n' || c=='\r' || len>=charlimit-1 ) + if( (*eof)==smtrue || c=='\n' || c=='\r' || len>=charlimit-1 ) { output[len]=0;//terminate str return len; @@ -538,12 +538,11 @@ smbool flashFirmwarePrimaryMCU( smbus smhandle, int deviceaddress, const smuint8 typedef enum { StatIdle=0, StatEnterDFU, StatFindDFUDevice, StatLoadFile, StatUpload, StatLaunch } UploadState;//state machine status -//free buffer and return given status code -FirmwareUploadStatus abortFWUpload( FirmwareUploadStatus stat, smuint8 *fwData, UploadState *state, int errorDetailCode ) +//handle error in FW upload +FirmwareUploadStatus abortFWUpload( FirmwareUploadStatus stat, UploadState *state, int errorDetailCode ) { globalErrorDetailCode=errorDetailCode; *state=StatIdle; - free(fwData); return stat; } @@ -558,6 +557,41 @@ FirmwareUploadStatus smFirmwareUpload( const smbus smhandle, const int smaddress { static smuint8 *fwData=NULL; static int fwDataLength; + static smbool fileLoaded=smfalse; + FirmwareUploadStatus state; + + //load file to buffer if not loaded yet + if(fileLoaded==smfalse) + { + if(loadBinaryFile(firmware_filename,&fwData,&fwDataLength)!=smtrue) + return FWFileNotReadable; + fileLoaded=smtrue; + } + + //update FW, called multiple times per upgrade + state=smFirmwareUploadFromBuffer( smhandle, smaddress, fwData, fwDataLength ); + + //if process complete, due to finish or error -> unload file. + if(((int)state<0 || state==FWComplete) && fileLoaded==smtrue) + { + free(fwData); + fileLoaded=smfalse; + } + + return state; +} + + +/** + * @brief smFirmwareUpload Sets drive in firmware upgrade mode if necessary and uploads a new firmware. Call this many until it returns value 100 (complete) or a negative value (error). + * @param smhandle SM bus handle, must be opened before call + * @param smaddress Target SM device address. Can be device in DFU mode or main operating mode. For Argon, one device in a bus must be started into DFU mode by DIP switches and smaddress must be set to 255. + * @param fwData pointer to memory address where .gdf file contents are loaded. Note: on some architectures (such as ARM Cortex M) fwData must be aligned to nearest 4 byte boundary to avoid illegal machine instructions. + * @param fwDataLenght number of bytes in fwData + * @return Enum FirmwareUploadStatus that indicates errors or Complete status. Typecast to integer to get progress value 0-100. + */ +FirmwareUploadStatus smFirmwareUploadFromBuffer( const smbus smhandle, const int smaddress, smuint8 *fwData, const int fwDataLength ) +{ static smuint32 primaryMCUDataOffset, primaryMCUDataLenth; static smuint32 secondaryMCUDataOffset,secondaryMCUDataLength; static UploadState state=StatIdle;//state machine status @@ -582,7 +616,7 @@ FirmwareUploadStatus smFirmwareUpload( const smbus smhandle, const int smaddress { if(deviceType==4000)//argon does not support restarting in DFU mode by software { - return abortFWUpload(FWConnectionError,fwData,&state,200); + return abortFWUpload(FWConnectionError,&state,200); } //restart device into DFU mode @@ -590,7 +624,7 @@ FirmwareUploadStatus smFirmwareUpload( const smbus smhandle, const int smaddress stat=smSetParameter(smhandle,smaddress,SMP_SYSTEM_CONTROL,64);//reset device to DFU command if(stat!=SM_OK) - return abortFWUpload(FWConnectionError,fwData,&state,300); + return abortFWUpload(FWConnectionError,&state,300); } else state=StatFindDFUDevice;//search DFU device in brute force, fallback for older BL versions that don't preserve same smaddress than non-DFU mode @@ -633,22 +667,19 @@ FirmwareUploadStatus smFirmwareUpload( const smbus smhandle, const int smaddress } if(i==256)//DFU device not found - return abortFWUpload(FWConnectingDFUModeFailed,fwData,&state,400);//setting DFU mode failed + return abortFWUpload(FWConnectingDFUModeFailed,&state,400);//setting DFU mode failed progress=3; } else if(state==StatLoadFile) { - if(loadBinaryFile(firmware_filename,&fwData,&fwDataLength)!=smtrue) - return FWFileNotReadable; - FirmwareUploadStatus stat=verifyFirmwareData(fwData, fwDataLength, deviceType, &primaryMCUDataOffset, &primaryMCUDataLenth, &secondaryMCUDataOffset, &secondaryMCUDataLength); if(stat!=FWComplete)//error in verify { - return abortFWUpload(stat,fwData,&state,100); + return abortFWUpload(stat,&state,100); } //all good, upload firmware @@ -662,7 +693,7 @@ FirmwareUploadStatus smFirmwareUpload( const smbus smhandle, const int smaddress smbool ret=flashFirmwarePrimaryMCU(smhandle,DFUAddress,fwData+primaryMCUDataOffset,primaryMCUDataLenth,&progress); if(ret==smfalse)//failed { - return abortFWUpload(FWConnectionError,fwData,&state,1000); + return abortFWUpload(FWConnectionError,&state,1000); } else { @@ -685,3 +716,4 @@ FirmwareUploadStatus smFirmwareUpload( const smbus smhandle, const int smaddress + diff --git a/devicedeployment.h b/devicedeployment.h index 4ba793e..f9cfaa1 100644 --- a/devicedeployment.h +++ b/devicedeployment.h @@ -54,6 +54,16 @@ typedef enum */ LIB FirmwareUploadStatus smFirmwareUpload(const smbus smhandle, const int smaddress, const char *firmware_filename ); +/** + * @brief smFirmwareUpload Sets drive in firmware upgrade mode if necessary and uploads a new firmware. Call this many until it returns value 100 (complete) or a negative value (error). + * @param smhandle SM bus handle, must be opened before call + * @param smaddress Target SM device address. Can be device in DFU mode or main operating mode. For Argon, one device in a bus must be started into DFU mode by DIP switches and smaddress must be set to 255. + * @param fwData pointer to memory address where .gdf file contents are loaded. Note: on some architectures (such as ARM Cortex M) fwData must be aligned to nearest 4 byte boundary to avoid illegal machine instructions. + * @param fwDataLenght number of bytes in fwData + * @return Enum FirmwareUploadStatus that indicates errors or Complete status. Typecast to integer to get progress value 0-100. + */ +FirmwareUploadStatus smFirmwareUploadFromBuffer( const smbus smhandle, const int smaddress, smuint8 *fwData, const int fwDataLength ); + typedef enum { CFGComplete=100, diff --git a/pcserialport.c b/pcserialport.c index 35a7668..5134a6d 100644 --- a/pcserialport.c +++ b/pcserialport.c @@ -41,16 +41,32 @@ smint32 serialPortOpen(const char * port_device_name, smint32 baudrate_bps) struct termios new_port_settings; int customBaudRate = 0; - port_handle = open(port_device_name, O_RDWR | O_NOCTTY); + port_handle = open(port_device_name, O_RDWR | O_NOCTTY | O_NONBLOCK); if(port_handle==-1) { smDebug(-1, Low, "Serial port error: port open failed"); - return(port_handle); + return -1; + } + + + // open() follows POSIX semantics: multiple open() calls to the same file will succeed + // unless the TIOCEXCL ioctl is issued (except for root) + if (ioctl(port_handle, TIOCEXCL) == -1) { + smDebug(-1, Low, "Serial port error: error setting TIOCEXCL"); + close(port_handle); + return -1; + } + + // as the port is now open, clear O_NONBLOCK flag for subsequent I/O calls + if (fcntl(port_handle, F_SETFL, 0) == -1) { + smDebug(-1, Low, "Serial port error: error clearing O_NONBLOCK"); + close(port_handle); + return -1; } switch(baudrate_bps) - { + { #if defined(B9600) case 9600 : baudrateEnumValue = B9600; break; #endif @@ -107,48 +123,61 @@ smint32 serialPortOpen(const char * port_device_name, smint32 baudrate_bps) #endif default: customBaudRate = 1; -#if defined(__APPLE__) - if (ioctl(port_handle, IOSSIOSPEED, &baudrate_bps) == -1) - { - smDebug(-1, Low, "Serial port error: unsupported baudrate\n"); - close(port_handle); - return -1; - } -#else - smDebug(-1,Low,"Serial port error: unsupported baudrate\n"); - close(port_handle); - return(-1); - break; -#endif - } + baudrateEnumValue=B9600;//must set something initially, changed later + break; + } memset(&new_port_settings, 0, sizeof(new_port_settings)); //reset struct - + cfmakeraw(&new_port_settings);//reset struct new_port_settings.c_cflag = CS8 | CLOCAL | CREAD; - new_port_settings.c_iflag = IGNPAR; - new_port_settings.c_oflag = 0; - new_port_settings.c_lflag = 0; + new_port_settings.c_iflag = IGNPAR; + new_port_settings.c_oflag = 0; + new_port_settings.c_lflag = 0; new_port_settings.c_cc[VMIN] = 0; /* non blocking mode */ new_port_settings.c_cc[VTIME] = readTimeoutMs/100; /* timeout 100 ms steps */ - if (!customBaudRate) - { #if defined(_BSD_SOURCE) - cfsetspeed(&new_port_settings, baudrateEnumValue); + cfsetspeed(&new_port_settings, baudrateEnumValue); #else - cfsetispeed(&new_port_settings, baudrateEnumValue); - cfsetospeed(&new_port_settings, baudrateEnumValue); + cfsetispeed(&new_port_settings, baudrateEnumValue); + cfsetospeed(&new_port_settings, baudrateEnumValue); #endif - } // Activate settings err = tcsetattr(port_handle, TCSANOW, &new_port_settings); if(err==-1) - { + { close(port_handle); smDebug(-1, Low, "Serial port error: failed to set port parameters"); return -1; - } + } + + if(customBaudRate) + { + #if defined(IOSSIOSPEED) + speed_t bps = baudrate_bps; + if (ioctl(port_handle, IOSSIOSPEED, &bps) == -1) + { + smDebug(-1, Low, "Serial port error: unsupported baudrate\n"); + close(port_handle); + return -1; + } + #else + smDebug(-1, Low, "Serial port error: unsupported baudrate\n"); + close(port_handle); + return -1; + #endif + } + + // set receive latency to 1 ms + #if defined(IOSSDATALAT) + unsigned long microsecs = 1000UL; + if (ioctl(port_handle, IOSSDATALAT, µsecs) == -1) { + smDebug(-1, Low, "Serial port error: error setting read latency"); + close(port_handle); + return -1; + } + #endif //flush any stray bytes from device receive buffer that may reside in it //note: according to following page, delay before this may be necessary http://stackoverflow.com/questions/13013387/clearing-the-serial-ports-buffer diff --git a/simplemotion_defs.h b/simplemotion_defs.h index 34dca1e..4f1bd96 100644 --- a/simplemotion_defs.h +++ b/simplemotion_defs.h @@ -576,6 +576,8 @@ #define SMP_TORQUE_EFFECT_FRICTION 242
//define inertia effect gain in torque control mode, torque added to setpoint equals -acceleration*gain
#define SMP_TORQUE_EFFECT_INERTIA 243
+//special smoothing filter. 0=disabled, other choices application dependent. this value is not saved in flash at the time of release, set it in run-time.
+#define SMP_SETPOINT_FILTER_MODE 244
//secondary feedback loop 300-399
//NOT IMPLEMENTED YET
diff --git a/tcpclient.c b/tcpclient.c index 31fb2f2..09d2426 100644 --- a/tcpclient.c +++ b/tcpclient.c @@ -56,7 +56,7 @@ int OpenTCPPort(const char * ip_addr, int port) fd_set myset; int res, valopt; socklen_t lon; - long arg; + unsigned long arg; #if defined(_WIN32) initwsa(); @@ -98,7 +98,7 @@ int OpenTCPPort(const char * ip_addr, int port) tv.tv_sec = 5; tv.tv_usec = 0; FD_ZERO(&myset); - FD_SET(sockfd, &myset); + FD_SET((unsigned int)sockfd, &myset); if (select(sockfd+1, NULL, &myset, NULL, &tv) > 0) { lon = sizeof(int); @@ -138,7 +138,7 @@ int PollTCPPort(int sockfd, unsigned char *buf, int size) int n; fd_set input; FD_ZERO(&input); - FD_SET(sockfd, &input); + FD_SET((unsigned int)sockfd, &input); struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = readTimeoutMs * 1000; @@ -155,14 +155,14 @@ int PollTCPPort(int sockfd, unsigned char *buf, int size) return(-1); } - n = read(sockfd, buf, size); + n = read(sockfd, (char*)buf, size); return(n); } int SendTCPByte(int sockfd, unsigned char byte) { int n; - n = write(sockfd, &byte, 1); + n = write(sockfd, (char*)&byte, 1); if(n<0) return(1); return(0); @@ -171,7 +171,7 @@ int SendTCPByte(int sockfd, unsigned char byte) int SendTCPBuf(int sockfd, unsigned char *buf, int size) { - int sent = write(sockfd, buf, size); + int sent = write(sockfd, (char*)buf, size); if (sent != size) { return sent; |
