====== USP serial protocol ====== USP is a serial communication protocol. The protocol is register based with 4 basic commands. Each protocol message contains Command ID, 1 or 2 bytes of ModuleID used for device addressing, data and checksum. Response message additionaly contains status byte. The protocol is designed for communication between one master and multiple slaves. Typically the PC host (master) communicates with a device(slave) over serial connection. The connection can be wired: RS232, RS485, Ethernet or wireless: Zig-Bee, 802.11(Wi-Fi) etc. ===== Terminology ===== * Master - the device issuing commands. Master is running USP client software. Master is identified by ModuleID = 0. * Slave - the device listening for USP commands. Slave is running USP server software. ===== Default RS232 and RS485 interface Communication Parameters ===== ^ Communication Parameter ^ Value ^ | Bits per second | 38400 | | Data Bits | 8 | | Stop Bits | 1 | | Parity | None | | Flow Control | None | *USP uses commands in Big-Endian format, 32 bit words e.g. the MSB of the first 32 bit word is sent first. ===== Generic Command format ===== All commands are referenced from the Master to the Slave where the Master is the host PC or an embedded controlling program, which issues the commands to the slave - PIC microcontroller based module which carries out the command. The format of the commands is described below. ==== Master -> Slave Command Format ==== ^ ^ bit 31-24 ^ bit 23-16 ^ bit 15-8 ^ bit 7-0 ^ ^ Command Word 1 (required) | Command ID | ModuleID-Hi | ModuleID-Lo | Command Length in 32 Bit Words | ^ Command Word 2 (Optional) | Data 1-3 | Data 1-2 | Data 1-1 | Data 1-0 | ^ Command Word 3 (Optional) | Data 2-3 | Data 2-2 | Data 2-1 | Data 2-0 | ^ Command Word n (Optional) | Data n-3 | Data n-2 | Data n-1 | Data n-0 | ^ Checksum Word (required) | Data | Data | Data | Checksum | *A command consists of two or more 32-bit words. The first 32-bit word is divided into 4 fields. The highest 8 bits (bits 31-24) identify the command. The next 16 bits (bits 23-8) is the ModuleID-Hi and ModuleID-Lo. The next 8 bits specify the number of 32 bit words in the command including the first and last word. *The command word is followed by optional 1 – N data words. The interpretation of data depends on command. *The last word contains 3 bytes of data (bits 21-16) and simple additive checksum (bits 7-0). ==== Slave -> Master Command Response Format ==== The Slave responds to every command only after the command has been completely received, not before. The response CommandID is the original CommandID + 0x80 That way it can be clearly distinguished the command and response on the communication channel with multiple slaves. The format of the response is similar to the command. ^ ^ bit 31-24 ^ bit 23-16 ^ bit 15-8 ^ bit 7-0 ^ ^ Response Word 1 (required) | Command ID + 0x80 | ModuleID-Hi | ModuleID-Lo | Response Length in 32 Bit Words | ^ Response Word 2 (Optional) | Data 1-3 | Data 1-2 | Data 1-1 | Data 1-0 | ^ Response Word 3 (Optional) | Data 2-3 | Data 2-2 | Data 2-1 | Data 2-0 | ^ Response Word n (Optional) | Data n-3 | Data n-2 | Data n-1 | Data n-0 | ^ Checksum Word (required) | Data | Data | ComStatus | Checksum | === ComStatus - Communication Status byte === ComStatus byte = 0 indicates that the command was completed successfully ^ Bit ^ Name ^ Description ^ ^ 0 | CSERR | 1 indicates check sum error | ^ 1 | TOUT | 1 Indicates module response timeout | ^ 2 | FBOOT | 1 indicates that module failed to respond after re-boot. | ^ 3 | CMERR | 1 indicates that module received unrecognized command | ^ 4 | ADERR | 1 indicates that module received unrecognized address | ^ 5 | PRERR | 1 indicates error during command processing| ^ 6 | LERR | 1 indicates that register is locked| ===== Addressing ===== Addess of the slave is carried in each packet in fields ModuleID-Hi and ModuleID-Lo. The use of addreses is application dependent but should adhere to the following rules: *Address 0 is the address of the device directly attached to the master *Address 255 is the broadcast address, all devices will execute the command *In multi-layer network such as combined wireless and wired network the ModuleID-Hi is the layer closer to the master. ===== Timeouts ===== Default packet timeout is 50ms. If device does not receive next byte of the packet within the timeout, it should seset the communication state machine to default and return into listen mode. The default timeout for the slave is 100ms. After timeout the master should report that the device did not respond and either retry or abort communication. The timeout can be extended as needed. ===== List Of Commads ===== ^ Command((Click command for detailed description and command syntax)) ^ CmdID ^ Notes ^ ^ [[usp:usp_spec#setregister_0x41|SetRegister(ModID, RegAddr, Value, Mask)]] | 0x41 | Sets 16 bit register to value. | ^ [[usp:usp_spec#getregister_0x42|GetRegister(ModID, RegAddr, Value)]] | 0x42 | Reads the 16 bit register value from slave. | ^ [[usp:usp_spec#setblock_0x43|SetBlock(ModID, RegAddr, DataBuffer, DataSize)]] | 0x43 | Writes block of 32 bit aligned data into slave. | ^ [[usp:usp_spec#getblock_0x44|GetBlock(ModID, RegAddr, DataBuffer, DataSize)]] | 0x44 | Reads block of 32 bit aligned data from slave. | ^ [[usp:usp_spec#setfregister_0x51|SetFRegister(ModID, RegAddr, Value, Mask)]] | 0x11 | Executes FLASH memory related command. | ^ [[usp:usp_spec#getfregister_0x52|GetFRegister(ModID, RegAddr, Value)]] | 0x12 | Reads status of FLASH memory related command | ^ [[usp:usp_spec#setfblock_0x43|SetFBlock(ModID, RegAddr, DataBuffer, DataSize)]] | 0x13 | Writes block of 32 bit aligned data into slave FLASH memory. | ^ [[usp:usp_spec#getfblock_0x44|GetFBlock(ModID, RegAddr, DataBuffer, DataSize)]] | 0x14 | Reads block of 32 bit aligned data from slave FLASH memory. | ^ [[usp:usp_spec#setfregister_0x51|SetERegister(ModID, RegAddr, Value, Mask)]] | 0x21 | Writes 16 bits of data into EEPROM memory. | ^ [[usp:usp_spec#getfregister_0x52|GetERegister(ModID, RegAddr, Value)]] | 0x22 | Reads the 16 bits of data from EEPROM memory | ^ [[usp:usp_spec#setfblock_0x43|SetEBlock(ModID, RegAddr, DataBuffer, DataSize)]] | 0x23 | Writes block of 32 bit aligned data into slave EEPROM memory. | ^ [[usp:usp_spec#getfblock_0x44|GetEBlock(ModID, RegAddr, DataBuffer, DataSize)]] | 0x24 | Reads block of 32 bit aligned data from slave EEPROM memory. | ^ [[usp:usp_spec&#sendbreak_0x55|SendBreak()]] | 0x55 | Break character. Used to send interrupt to USP master | ^ [[usp:usp_spec#clearbreak_0x56|ClearBreak()]] | 0x56 | Clear break and receive STATUS | In order to implement some rudimentary check if the command word is a valid command, the following filter may be used: ((MSB == 0) && ((CMD_ID&0x70) >0))==1 -valid command ==== C function headers ==== === USP Return Value === USP protocol functions return standard 16 bit USP return value. The return value comprises the response status byte and indicator flags, such as timeout or parity error: ^ Bit ^ Description ^ ^ 0 - 7 | Received status byte | ^ 8 - 15 | 0 .. no error | ^ | 1 .. reponse timeout | ^ | 2 .. invalid checksum of the response | /****************************************************************************** * Function: UInt16 USP_SetRegister(UInt16 a_iModID, UInt16 a_iAddr, UInt16 a_iVal, UInt16 a_iMask) * * Input: USP protocol data: * UInt16 a_iModID : Module address (2nd byte + 3rd byte in USP frame) * UInt16 a_iAddr : Register address to be modified * UInt16 a_iVal : Desired register value * UInt16 a_iMask : Mask applied to the data, 1: the register bit will be modified, 0: the registr bit will be unmodified * * Output: USP return value: * bit 0 - 7 : Received status byte * bit 8 - 15 :| 0 .. no error, 1 .. reponse timeout, 2 .. invalid checksum of the response * * Overview: Sets value of register using USP protocol. * * Note: None *****************************************************************************/ UInt16 USP_SetRegister(UInt16 a_iModID, UInt16 a_iAddr, UInt16 a_iVal, UInt16 a_iMask); /****************************************************************************** * Function: UInt16 USP_GetRegister(UInt16 a_iModID, UInt16 a_iAddr, UInt16 *a_oVal) * * Input: UInt16 a_iModID : Module address (2nd byte + 3rd byte in USP frame) * UInt16 a_iAddr : Register address to be modified * UInt16 a_oVal : Pointer to UInt16 variable, register value * * Output: USP return value: * bit 0 - 7 : Received status byte * bit 8 - 15 :| 0 .. no error, 1 .. reponse timeout, 2 .. invalid checksum of the response * * Overview: Reads value of register using USP protocol * * Note: None *****************************************************************************/ UInt16 USP_GetRegister(UInt16 a_iModID, UInt16 a_iAddr, UInt16 *a_oVal); /****************************************************************************** * Function: UInt16 USP_SetBlock(UInt16 a_iModID, UInt16 a_iAddr, UInt8 *a_pBuff, UInt16 a_iSize) * * Input: USP protocol data: * UInt16 a_iModID : Module address (2nd byte + 3rd byte in USP frame) * UInt16 a_iAddr : Register address to be modified * UInt8 a_pBuff : Pointer to data to be sent * UInt16 a_iSize : Size of the data to send, number of 32bit words. * * Output: USP return value: * bit 0 - 7 : Received status byte * bit 8 - 15 :| 0 .. no error, 1 .. reponse timeout, 2 .. invalid checksum of the response * * Overview: Sets block of registers, starting at address a_iAddr using USP protocol * *****************************************************************************/ UInt16 USP_SetBlock(UInt16 a_iModID, UInt16 a_iAddr, UInt8 *a_pBuff, UInt16 a_iSize); /****************************************************************************** * Function: UInt16 USP_GetBlock(UInt16 a_iModID, UInt16 a_iAddr, UInt8 *a_pBuff, UInt16 a_iSize) * * Input: USP protocol data: * UInt16 a_iModID : Module address (2nd byte + 3rd byte in USP frame) * UInt16 a_iAddr : Register address to be modified * UInt8 a_pBuff : Pointer to data array for output data * UInt16 a_iSize : Size of the data to retrieve, number of 32bit words. * * Output: USP return value: * bit 0 - 7 : Received status byte * bit 8 - 15 :| 0 .. no error, 1 .. reponse timeout, 2 .. invalid checksum of the response * * Overview: Reads block of registers, starting at address a_iAddr using USP protocol * *****************************************************************************/ UInt16 USP_GetBlock(UInt16 a_iModID, UInt16 a_iAddr, UInt8 *a_pBuff, UInt16 a_iSize) ==== SetRegister() [0x41] ==== This command sets the register value at the Address of slave to value XXXX using the mask MMMM. The mask has 1 in the position of bit that will be affected by value XXXX, 0 in mask marks bit(s) that are not affected by the command. **Command** ^ Word # ^ bit 31-24 ^ bit 23-16 ^ bit 15-8 ^ bit 7-0 ^ ^ 1 Header | 0x41 | Sl. Mod. ID Hi | Sl. Mod. ID Lo | 0x03 | ^ 2 Data | MM Hi | MM Lo | XX Hi | XX Lo | ^ 3 Data, Checksum | Address Hi | Address Lo | 0x00 | Checksum | **Response** ^ Word # ^ bit 31-24 ^ bit 23-16 ^ bit 15-8 ^ bit 7-0 ^ ^ 1 Header | 0xC1 | Sl. Mod. ID Hi | Sl. Mod. ID Lo | 0x02 | ^ 2 Data, Checksum | Register Hi | Register Lo | Status | Checksum | **Example:** Set register 0x0008, bits 1 and 2 to 1. Command Word 1 = 0x41000003 Command Word 2 = 0x00060006 Command Word 3 = 0x000800ch Response Word 1= 0xC1000002 Response Word 2= 0x333600ch *Note that the bits 7-3,0 of the register 0x0008 were not affected by the command ==== GetRegister() [0x42] ==== This command reads the content of a 16 bit register in the slave. **Command** ^ Word # ^ bit 31-24 ^ bit 23-16 ^ bit 15-8 ^ bit 7-0 ^ ^ 1 Header | 0x42 | Sl. Mod. ID Hi | Sl. Mod. ID Lo | 0x02 | ^ 3 Data, Checksum | Address Hi | Address Lo | 0x00 | Checksum | **Response** ^ Word # ^ bit 31-24 ^ bit 23-16 ^ bit 15-8 ^ bit 7-0 ^ ^ 1 Header | 0xC1 | Sl. Mod. ID Hi | Sl. Mod. ID Lo | 0x02 | ^ 2 Data, Checksum | Register Hi | Register Lo | Status | Checksum | **Example:** Read register 0x0008 Command Word 1 = 0x42000002 Command Word 2 = 0x000800ch Response Word 1= 0xC2000002 Response Word 2= 0x333600ch ==== SetBlock() [0x43] ==== Writes block of 32 bit aligned data into slave starting at the Address. The Address must be 32 bit aligned. Status indicates wherever the command was successful. **Command** ^ Word # ^ bit 31-24 ^ bit 23-16 ^ bit 15-8 ^ bit 7-0 ^ ^ 1 Header | 0x43 | Sl. Mod. ID Hi | Sl. Mod. ID Lo | 0xN | ^ 2 Data | Data 1-3 | Data 1-2 | Data 1-1 | Data 1-0 | ^ N-1 Data | Data n-3 | Data n-2 | Data n-1 | Data n-0 | ^ N Checksum | Address Hi | Address Lo | 0x00 | Checksum | **Response** ^ Word # ^ bit 31-24 ^ bit 23-16 ^ bit 15-8 ^ bit 7-0 ^ ^ 1 Header | 0xC3 | Sl. Mod. ID Hi | Sl. Mod. ID Lo | 0x02 | ^ 2 Status, Checksum | 0x00 | 0x00 | Status | Checksum | **Example:** Set block of 2 words starting at 0x0108, to 0xA5A5FFFF Command Word 1 = 0x43000004 Command Word 2 = 0xA5A5FFFF Command Word 3 = 0xA5A5FFFF Command Word 4 = 0x010800ch Response Word 1= 0xC3000002 Response Word 2= 0x000000ch ==== GetBlock() [0x44] ==== Reads block of data from IMS memory **Command** ^ Word # ^ bit 31-24 ^ bit 23-16 ^ bit 15-8 ^ bit 7-0 ^ ^ 1 Header | 0x44 | Sl. Mod. ID Hi | Sl. Mod. ID Lo | 0x03 | ^ 2 Data Length | 0x00 | 0x00 | Data Len Hi | Data Len Lo | ^ 3 Checksum | Address Hi | Address Lo | 0x00 | Checksum | **Response** ^ Word # ^ bit 31-24 ^ bit 23-16 ^ bit 15-8 ^ bit 7-0 ^ ^ 1 Header | 0xC4 | Sl. Mod. ID Hi | Sl. Mod. ID Lo | 0x0N | ^ 2 Data 1 | Data 1-3 | Data 1-2 | Data 1-1 | Data 1-0 | ^ N-1 Data | Data n-3 | Data n-2 | Data n-1 | Data n-0 | ^ N Status, Checksum | 0x00 | 0x00 | Status | Checksum | **Example:** Read block of 2 words starting at 0x0108 Command Word 1 = 0x44000002 Command Word 2 = 0x010800ch Response Word 1= 0xC4000004 Response Word 2= 0xA5A5FFFF Response Word 3= 0xA5A5FFFF Response Word 4= 0x000000ch ==== SetFRegister() [0x11] ==== This command should be used for operations with device FLASH memory. The description is the same as SetRegister() ==== GetFRegister() [0x12] ==== This command should be used for operations with device FLASH memory. The description is the same as GetRegister() ==== SetFBlock() [0x13] ==== This command should be used for operations with device FLASH memory. The description is the same as SetBlock() ==== GetFBlock() [0x14] ==== This command should be used for operations with device FLASH memory. The description is the same as GetBlock() ==== SetERegister() [0x21] ==== This command should be used for operations with device EEPROM memory. The description is the same as SetRegister() ==== GetERegister() [0x22] ==== This command should be used for operations with device EEPROM memory. The description is the same as GetRegister() ==== SetEBlock() [0x23] ==== This command should be used for operations with device EEPROM memory. The description is the same as SetBlock() ==== GetEBlock() [0x24] ==== This command should be used for operations with device EEPROM memory. The description is the same as GetBlock() ==== SendBreak() [0x55] ==== This command sends break up the USP chain. When the slave device needs to signal that it has a status change it may send break signal to the master device. The signal is one 32 bit word, it comprises break character command ID (0x55) and USP Slave module ID. Master will recoginze break by checking that CommandID == 0x55 and the Length == 1 **Command** ^ Word # ^ bit 31-24 ^ bit 23-16 ^ bit 15-8 ^ bit 7-0 ^ ^ 1 Header | 0x55 | Sl. Mod. ID (Hi) | Sl. Mod. ID Lo/Len Hi | 0x01 | **Response** None. The break is cleared by ClearBreak() command from master. The slave will keep sending break signal in periodic intervals until master will clear the break using ClearBreak() command. The default resend interval is 100ms. **Example:** Device with address 0x22 sends break: Break Word 1 = 0x55220001 ==== ClearBreak() [0x56] ==== This command clears the break signal from slave. Upon receiving the command, the slave clears the break bit to stop sending break signal and responds with the status register content. Any forwarding devices will also clear their respective break bit and stop sending break upstream. **Command** ^ Word # ^ bit 31-24 ^ bit 23-16 ^ bit 15-8 ^ bit 7-0 ^ ^ 1 Header | 0x56 | Sl. Mod. ID (Hi) | Sl. Mod. ID Lo/Len Hi | 0x02 | ^ 3 Data, Checksum | 00 | 0x04 | 0x00 | Checksum | Note: Address field is filled with the address of the REG_STATUS (default value 0x04) **Response** ^ Word # ^ bit 31-24 ^ bit 23-16 ^ bit 15-8 ^ bit 7-0 ^ ^ 1 Header | 0xD6 | Sl. Mod. ID (Hi) | Sl. Mod. ID Lo/Len Hi | 0x02 | ^ 2 Data, Checksum | Status Hi | Status Lo | Status | Checksum | **Example:** Clear break from device ID 0x22 Command Word 1 = 0x56000002 Command Word 2 = 0x000400ch Response Word 1= 0xD6000002 Response Word 2= 0x000500ch Slave REG_STATUS value is 0x05, the break is cleared. ===== USP configuration file ===== Ability to execute list of USP commands is implemented by reading or writing USP config file into a USP device. USP client on PC opens a USP configuartion file reads and executes each line one by one. The commands are executed in the same order as they are written in the file. The format of the file is following: Command ModuleID Parameters ;Comment List of commands: ^ Config name ^ Parameters ^ Description | | SR | ModuleID RegisterAddress Value Mask | SetRegister | | GR | ModuleID RegisterAddress | GetRegister | | SB | ModuleID RegisterAddress (NumberOfWords Words ... OR "text" ) | SetBlock | | GB | ModuleID RegisterAddress NumberOfWords | GetBlock | | DELAY | Value((ms)) | Stop execution and wait Value miliseconds. | * **;** character is a comment delimiter, any characters to the right of the ; until end of the line will be ignored * **"** character is a text delimiter, anything in "" will be converted to binary using ASCII table, example: "text can include ;" * If the number of characteds need to be 32 bit aligned, eg in SetBlock any missing characters will be padded with 0 * **0x** or **0X** is parsed as a hexadecinal number The commands are executed in the order in which they are in the file.