using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO.Ports; using System.IO; using System.Text.RegularExpressions; using System.Configuration; using System.Timers; namespace Daya_Bay_Princeton_2009 { public class SerialPortCommunication { string filename = null; private MainForm mainForm; //Reference to The Main Form static int maxData = 240; //Keeps the Data Frame from overrunning private int byteCtr = 0; //Byte Counter private byte rxHeader = 0; private byte seqNo, reqNo; private int lastError; private uint prolongFactor = Constants.DefaultProlong; private uint timeout = Constants.DefaultTimeout; private byte[] blkout = new byte[Constants.MaxDataBytes]; /* Transmit buffer */ private byte[] rxFrame = new byte[Constants.MaxFrameSize]; private byte[] blkin = new byte[Constants.MaxDataBytes]; /* Receive buffer */ private int error = Constants.ErrorNone; private int meraseCycles = 20; bool ProgramF = true; bool MSP430X = false; const int MODE_BSL = 1; string passwdFile = null; const ushort protocolMode = MODE_BSL; const byte BSL_SYNC = 0x80; private SerialPort SerialPort; //Reference to SerialPort private List AllPorts; public SerialPortCommunication(MainForm parentForm,string PortName) { SerialPort = new SerialPort(); SerialPort.PortName = PortName; mainForm = parentForm; filename = mainForm.filename; AllPorts = parentForm.AllPorts; } public SerialPort _SERIALPORT { get { return SerialPort; } set { SerialPort = value; } } public void InitializePorts(int Ports) { //****Important Function***** //Creates SerialPortCommunication Instances and adds all the Valid ones to the AllPorts List int StartingPortNumber = Properties.Settings.Default.ComportStartingNumber; //Empties the AllPorts first AllPorts.Clear(); int UsablePorts = Ports; for (int i = StartingPortNumber; i < (UsablePorts + StartingPortNumber); i++) { PortName = "Com" + i; AllPorts.Add(new SerialPortCommunication(this, PortName)); } } public int comInit(string PortName) { try { if (SerialPort.IsOpen == true) { SerialPort.Close(); } SerialPort.DataReceived += new SerialDataReceivedEventHandler(_serialPort_DataReceived); SerialPort.BaudRate = 9600; SerialPort.Parity = Parity.Even; SerialPort.DataBits = 8; SerialPort.StopBits = StopBits.One; SerialPort.DtrEnable = true; SerialPort.RtsEnable = true; SerialPort.ReadTimeout = 0; SerialPort.WriteTimeout = 50; SerialPort.WriteBufferSize = 512; SerialPort.ReadBufferSize = 256; seqNo = 0; reqNo = 0; SerialPort.ParityReplace = 0xff; SerialPort.Open(); SerialPort.DiscardInBuffer(); SerialPort.DiscardOutBuffer(); return 1; } catch { mainForm.textBoxStatus.AppendText(PortName + " is not working\r\n"); return 1; } } public void bslReset(Boolean invokeBSL, string Portname) { try { if (SerialPort.IsOpen == true) { SerialPort.Close(); } SerialPort.Open(); setRstPin(true); setTestPin(true); System.Threading.Thread.Sleep(250); if (invokeBSL) { setRstPin(false); System.Threading.Thread.Sleep(10);/* TEST pin: GND */ setTestPin(true); System.Threading.Thread.Sleep(10);/* TEST pin: Vcc */ setTestPin(false); System.Threading.Thread.Sleep(10);/* TEST pin: GND */ setTestPin(true); System.Threading.Thread.Sleep(10); /* TEST pin: Vcc */ setTestPin(false); System.Threading.Thread.Sleep(10);/* TEST pin: GND */ setRstPin(true); System.Threading.Thread.Sleep(10);/* RST pin: Vcc */ setTestPin(true); /* TEST pin: GND */ } else { setRstPin(false); /* RST pin: GND */ System.Threading.Thread.Sleep(30); /* delays */ setRstPin(true); } System.Threading.Thread.Sleep(250); SerialPort.DiscardInBuffer(); SerialPort.DiscardOutBuffer(); mainForm.textBoxStatus.AppendText(SerialPort.PortName + " is working\r\n"); } catch (Exception) { mainForm.textBoxStatus.AppendText(SerialPort.PortName + " is not working\r\n"); } } public int MassErases() { int meraseCycles = 2; int i; mainForm.textBoxStatus.AppendText("Mass Erase...\r\n"); mainForm.textBoxStatus.Refresh(); for (i = 0; i < meraseCycles; i++) { if (i == 1) { mainForm.textBoxStatus.AppendText("Additional mass erase cycles...\r\n"); //textBox1.Refresh(); } bslTxRx(Constants.BSLMassErase, /* Command: Mass Erase */ 0xff00, /* Any address within flash memory. */ 0xa506, /* Required setting for mass erase! */ null, blkin); { } } passwdFile = null; /* No password file required! */ return 1; } public int txPasswd(string passwdFile) { int i; if (passwdFile == null) { /* Send "standard" password to get access to protected functions. */ /* Fill blkout with 0xff * (Flash is completely erased, the contents of all Flash cells is 0xff) */ for (i = 0; i < 0x20; i++) { blkout[i] = 0xff; } return (bslTxRx(Constants.ActionpPassword, /* Command: Transmit Password */ 0xffe0, /* Address of interupt vectors */ 0x0020, /* Number of bytes */ blkout, blkin)); } else { /* Send TI TXT file holding interrupt vector data as password: */ // textBox1.Text = "Transmit PSW file"; // return (programTIText(passwdFile, ACTION_PASSWD)); return 1; } } public void setTestPin(Boolean level)//Controls TEST pin (0: VCC; 1: GND) { if (level == true) { SerialPort.RtsEnable = true; } else { SerialPort.RtsEnable = false; } SerialPort.RtsEnable = level ? SerialPort.RtsEnable = true : SerialPort.RtsEnable = false; } public void setRstPin(Boolean level)//Controls RST/NMI pin (0: GND; 1: VCC) { if (level == true) { SerialPort.DtrEnable = true; } else { SerialPort.DtrEnable = false; } SerialPort.DtrEnable = level ? SerialPort.DtrEnable = true : SerialPort.DtrEnable = false; } public int programBlk(uint addr, ushort len, uint action) { int error = Constants.ErrorNone; if ((action & Constants.ActionpPassword) != 0) { return (bslTxRx(Constants.BSLSendPassword, addr, len, blkout, blkin)); } /* if ACTION_PASSWD */ /* Check, if specified range is erased: */ if (action == Constants.ActionEraseCheck) error = verifyBlk(addr, len, action & Constants.ActionEraseCheck); else if (action == Constants.ActionEraseCheckFast) error = verifyBlk(addr, len, action & Constants.ActionEraseCheckFast); if (error != Constants.ErrorNone) { return (error); } if ((action & Constants.ActionProgram) != 0) { mainForm.textBoxStatus.AppendText("Program starting at " + addr + " " + len + " bytes\r\n"); mainForm.textBoxStatus.Refresh(); error = Constants.ErrorNone; if (error != Constants.ErrorNone) return (error); /* Set Offset: */ if (MSP430X == true) bslTxRx(Constants.BSLMemOffset, 0, (ushort)(addr >> 16), blkout, blkin); if (error != Constants.ErrorNone) return (error); /* Program block: */ error = bslTxRx(Constants.BSLTransmitBlock, addr, len, blkout, blkin); //printf("Error: %i\n", error); if (error != Constants.ErrorNone) { return (error); /* Cancel, if error (ACTION_VERIFY is skipped!) */ } if (MSP430X == true) if (bslTxRx(Constants.BSLMemOffset, 0, (ushort)(0), null, blkin) != 0) return (error); } /* if Constants.ActionProgram */ /* Verify block: */ error = verifyBlk(addr, len, action & Constants.ActionVerify); if (error != Constants.ErrorNone) { return (error); } return (error); } /* programBlk */ public int ProgramFile(string filename) { if (ProgramF == true) { /* Parse file in TXT-Format and program data into flash memory. */ mainForm.textBoxStatus.AppendText("Program" + filename + "\r\n"); if ((error = programTIText(filename, Constants.ActionProgram)) != Constants.ErrorNone) { // read out error address+3 from RAM (error address buffer) if ((Constants.Constants.LoadedModel == Constants.LargeRamModel) || (Constants.LoadedModel == Constants.SmallRamModel)) { if (MSP430X == true) if (bslTxRx(Constants.BSLMemOffset, 0, 0, null, blkin) != 0) signOff(error, true); if ((error = bslTxRx(Constants.BSLReceiveBlock, 0X021E, 2, null, blkin)) == Constants.ErrorNone) { _err = (blkin[1] << 8) + blkin[0]; } else return (signOff(error, false)); } else return (signOff(Constants.ErrorVerifyFailed, false)); } else { mainForm.textBoxStatus.AppendText(" " + byteCtr + " bytes programmed\r\n"); } } return 1; } public int bslSync() /* Transmits Synchronization character and expects to * receive Acknowledge character * Return == 0: OK * Return == 1: Sync. failed. */ { byte[] ch = new byte[1]; int chback; int loopcnt; const byte cLoopOut = 3; /* Max. trials to get synchronization */ for (loopcnt = 0; loopcnt < cLoopOut; loopcnt++) try { SerialPort.DiscardInBuffer(); ch[0] = BSL_SYNC; SerialPort.ReadTimeout = 50; SerialPort.Write(ch, 0, 1); chback = SerialPort.ReadByte(); if (chback == Constants.DataAcknowledge) { return (Constants.ErrorNone); } else return (Constants.ErrorBSLSync); } catch (Exception ex) { } return (Constants.ErrorBSLSync); } int comWaitForData(int count, uint timeout) /* exported! */ { int rxCount = 0; uint startTime = (uint)Environment.TickCount; do { int d = SerialPort.BytesToRead; } while (((rxCount = SerialPort.BytesToRead) < count) && (calcTimeout(startTime) <= timeout)); return (rxCount); } public uint calcTimeout(uint startTime) /* exported! */ { return ((uint)Environment.TickCount - startTime); } public void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { } private bool WriteTITextBytes(uint ulAddress, ushort wWordCount, ushort lpData) { uint i; return false; { } for (i = 0; i < (wWordCount * 2); i++) { return true; } } bool StartTITextOutput(byte FileName) { FileStream file = new FileStream("blink2.txt", FileMode.Open, FileAccess.Read, FileShare.Read); StreamReader sr = new StreamReader(file); string s = sr.ReadToEnd(); sr.Close(); file.Close(); return (s != null); } public int bslTxRx(byte cmd, uint addr, ushort len, byte[] blkout, byte[] blkin) { byte[] dataOut = new byte[MAX_FRAME_SIZE]; ushort length = 4; if (cmd == BSL_TXBLK) { /* Align to even start address */ if ((addr % 2) != 0) { /* Decrement address and */ addr--; /* fill first byte of blkout with 0xFF */ Array.Copy(blkout, 1, blkout, 0, len); blkout[0] = 0xFF; len++; } /* Make sure that len is even */ if ((len % 2) != 0) { /* Inc. len and fill last byte of blkout with 0xFF */ blkout[(len++)] = 0xFF; } } if (cmd == BSL_RXBLK) { /* Align to even start address */ if ((addr % 2) != 0) { /* Decrement address but */ addr--; /* request an additional byte. */ len++; } /* Make sure that len is even */ if ((len % 2) != 0) { len++; } } if ((cmd == BSL_TXBLK) || (cmd == BSL_TXPWORD)) { length = (ushort)(len + 4); } /* Add necessary information data to frame: */ dataOut[0] = (byte)(addr & 0x00ff); dataOut[1] = (byte)((addr >> 8) & 0x00ff); dataOut[2] = (byte)(len & 0x00ff); dataOut[3] = (byte)((len >> 8) & 0x00ff); if (blkout != null) { /* Copy data out of blkout into frame: */ Array.Copy(blkout, 0, dataOut, 4, len); } if (bslSync() != Constants.ErrorNone) { return (Constants.ErrorBSLSync); } /* Send frame: */ comTxRx(cmd, dataOut, (byte)length); if (blkin != null) { /* Copy received data out of frame buffer into blkin: */ Array.Copy(rxFrame, 4, blkin, 0, rxFrame[2]); } return (Constants.ErrorNone); } public int comTxRx(byte cmd, byte[] dataOut, byte length) /* Sends the command cmd with the data given in dataOut to the * microcontroller and expects either an acknowledge or a frame * with result from the microcontroller. The results are stored * in dataIn (if not a NULL pointer is passed). * In this routine all the necessary protocol stuff is handled. * Returns zero if the function was successful. */ { byte[] txFrame = new byte[MAX_FRAME_SIZE]; ushort checksum = 0; int k = 0; int errCtr = 0; byte[] dataOut4096 = new byte[4096]; byte rxNum = 0; int resentFrame = 0; /* Transmitting part ----------------------------------------*/ /* Prepare data for transmit */ if ((length % 2) != 0) { /* Fill with one byte to have even number of bytes to send */ if (protocolMode == MODE_BSL) dataOut[length++] = 0xFF; // fill with 0xFF else dataOut[length++] = 0; // fill with zero } txFrame[0] = (byte)(DATA_FRAME | seqNo); txFrame[1] = cmd; txFrame[2] = length; txFrame[3] = length; reqNo = (byte)((seqNo + 1) % MAX_FRAME_COUNT); Array.Copy(dataOut, 0, txFrame, 4, length); checksum = calcChecksum(txFrame, (ushort)(length + 4)); txFrame[length + 4] = (byte)(checksum); txFrame[length + 5] = (byte)(checksum >> 8); { ushort accessAddr = (ushort)((0x0212 + (checksum ^ 0xffff)) & 0xfffe); //if (BSLMemAccessWarning && (accessAddr < BSL_CRITICAL_ADDR)) //{ // //textBox1.Text = "This command might change data at " + accessAddr; // /* 0x0212: Address of wCHKSUM */ //} } /* Transmit data: */ k = 0; /* Clear receiving queue: */ SerialPort.DiscardInBuffer(); Array.Clear(blkin, 0, 250); //PurgeComm(hComPort, PURGE_RXCLEAR | PURGE_RXABORT); do { SerialPort.Write(txFrame, k++, 1); } while (k < length + 6);//&& (_serialPort.BytesToRead == 0)); /* Check after each transmitted character, * if microcontroller did send a character (probably a NAK!). */ //int x = _serialPort.BytesToRead; /* Receiving part -------------------------------------------*/ rxFrame[2] = 0; rxFrame[3] = 0; /* Set lengths of received data to 0! */ do { lastError = 0; /* Clear last error */ if (comRxHeader(ref rxHeader, rxNum, (timeout * prolongFactor)) == 0) /* prolong timeout to allow execution of sent command */ { /* => Header received */ do { resentFrame = 0; switch (rxHeader) { case Constants.DataAcknowledge: if (rxNum == reqNo) { seqNo = reqNo; return (lastError = Constants.ErrorNone); /* Acknowledge received correctly => next frame */ } break; /* case DATA_ACK */ case Constants.DataNAN: return (lastError = ERR_RX_NAK); break; /* case DATA_NAK */ case Constants.DataFrame: if (rxNum == reqNo) if (comRxFrame(rxHeader, rxNum) == 0) return (lastError = Constants.ErrorNone); break; /* case DATA_FRAME */ case CMD_FAILED: /* Frame ok, but command failed. */ return (lastError = ERR_CMD_FAILED); break; /* case CMD_FAILED */ default: break; } /* switch */ errCtr = Constants.MaxErrorCount; } while ((resentFrame == 0) && (errCtr < Constants.MaxErrorCount)); } /* if (comRxHeader) */ else { /* => Timeout while receiving header */ errCtr = Constants.MaxErrorCount; } /* else (comRxHeader) */ } while (errCtr < Constants.MaxErrorCount); if (lastError == ERR_CMD_NOT_COMPLETED) { /* Accept QUERY_RESPONSE as real ACK and correct Seq.-No.: */ seqNo = reqNo; } if (lastError == Constants.ErrorNone) return (lastError = ERR_COM); else return (lastError); } /* comTxRx */ public int comRxFrame(byte rxHeader, byte rxNum) { ushort checksum; byte rxLength; ushort rxLengthCRC; int x = 0; rxFrame[0] = (byte)(DATA_FRAME | rxNum); if (comWaitForData(3, timeout) >= 3) { SerialPort.Read(rxFrame, 1, 3); //_serialPort.Read(rxFrame, 1, 3); if ((rxFrame[1] == 0) && (rxFrame[2] == rxFrame[3])) { rxLength = rxFrame[2]; /* Pointer to rxFrame[2] */ rxLengthCRC = (ushort)(rxLength + 2); /* Add CRC-Bytes to length */ if (comWaitForData(rxLengthCRC, timeout) >= rxLengthCRC) { System.Threading.Thread.Sleep(10); SerialPort.Read(rxFrame, 4, rxLengthCRC); x = SerialPort.BytesToRead; /* Check received frame: */ checksum = calcChecksum(rxFrame, (ushort)(rxLength + 4)); /* rxLength+4: Length with header but w/o CRC */ if ((rxFrame[rxLength + 4] == (byte)checksum) && (rxFrame[rxLength + 5] == (byte)(checksum >> 8))) { return (Constants.ErrorNone); /* Frame received correctly (=> send next frame) */ } /* if (Checksum correct?) */ } /* if (Data: no timeout?) */ } /* if (Add. header info. correct?) */ } /* if (Add. header info.: no timeout?) */ return (ERR_COM); /* Frame has errors! */ } /* comRxFrame */ public int comRxHeader(ref byte rxHeader, byte rxNum, uint timeout) { byte[] Hdr = new byte[1]; if (comWaitForData(1, timeout) >= 1) { SerialPort.Read(Hdr, 0, 1); rxHeader = (byte)(Hdr[0] & 0xf0); rxNum = (byte)(Hdr[0] & 0x0f); if (protocolMode == MODE_BSL) { reqNo = 0; seqNo = 0; rxNum = 0; } return (Constants.ErrorNone); } else { rxHeader = 0; rxNum = 0; return (lastError = ERR_RX_HDR_TIMEOUT); } } public ushort calcChecksum(byte[] data, ushort length) { // The return value. ushort retVal = 0; // Cycle through the bytes. for (ushort index = 0; index < length / 2; ++index) { // Get the current unsigned short. ushort current = BitConverter.ToUInt16(data, index * 2); ushort test = current; // Alter the checksum. retVal ^= current; } // Return the checksum. return (ushort)(retVal ^ 0xffff); } public int programTIText(string filename, uint action) { int error = Constants.ErrorNone; int linelen = 0; int linepos = 0; int KBytes, KBytesbefore = -1; ushort dataframelen = 0; uint currentAddr = 0; char[] strdata = new char[128]; string LinetoString; //StreamReader infile= new StreamReader(new FileStream("c:\\blink2.txt", FileMode.Open, FileAccess.Read, FileShare.Read)); StreamReader infile = new StreamReader(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read)); byteCtr = 0; if (infile != null) /* Convert data for MSP430, TXT-File is parsed line by line: */ while (true) /* FRGR */ { /* Read one line: */ LinetoString = infile.ReadLine(); LinetoString = LinetoString + Environment.NewLine; for (int j = 0; j < LinetoString.Length; ++j) LinetoString.CopyTo(j, strdata, j, 1); if ((strdata[0] == null) || (strdata[0] == 'q')) { /* => send frame and quit */ if (dataframelen > 0) /* Data in frame? */ { error = programBlk(currentAddr, dataframelen, action); byteCtr += dataframelen; /* Byte Counter */ dataframelen = 0; } break; /* FRGR */ } linelen = LinetoString.Length; if (strdata[0] == '@') /* if @ => new address => send frame and set new addr. */ { if (dataframelen > 0) { error = programBlk(currentAddr, dataframelen, action); byteCtr += dataframelen; /* Byte Counter */ dataframelen = 0; } //currentAddr = 16384; UInt32.TryParse((LinetoString.Substring(1, 4)), System.Globalization.NumberStyles.HexNumber, null, out currentAddr); //sscanf(strdata[1], "%lx\n", currentAddr); continue; } /* Transfer data in line into blkout: */ for (linepos = 0; linepos < linelen - 3; linepos += 3, dataframelen++) { Byte.TryParse((LinetoString.Substring(linepos, 2)), System.Globalization.NumberStyles.HexNumber, null, out (blkout[dataframelen])); /* (Max 16 bytes per line!) */ } if (dataframelen > maxData - 16) /* if frame is getting full => send frame */ { error = programBlk(currentAddr, dataframelen, action); byteCtr += dataframelen; /* Byte Counter */ currentAddr += dataframelen; dataframelen = 0; /* bargraph: indicates succession, actualize only when changed. FRGR */ KBytes = (byteCtr + 512) / 1024; if (KBytesbefore != KBytes) { KBytesbefore = KBytes; //printf("\r%02d KByte ", KBytes); //printf("\xDE"); //for (i=0;i> 16), null, blkin) != 0) return (error); addr = addr & 0xFFFF; } error = bslTxRx(BSL_RXBLK, addr, len, null, blkin); //printf("Error: %i\n", error); if (error != Constants.ErrorNone) { return (error); /* Cancel, if read error */ } else { for (i = 0; i < len; i++) { if ((action & ACTION_VERIFY) != 0) { /* Compare data in blkout and blkin: */ if (blkin[i] != blkout[i]) { //printf("Verification failed at %x (%x, %x)\n", addr+i, blkin[i], blkout[i]); return (ERR_VERIFY_FAILED); /* Verify failed! */ } continue; } if ((action & ACTION_ERASE_CHECK) != 0) { /* Compare data in blkin with erase pattern: */ if (blkin[i] != 0xff) { //printf("Erase Check failed at %x (%x)\n", addr+i, blkin[i]); return (ERR_ERASE_CHECK_FAILED); /* Erase Check failed! */ } continue; } /* if ACTION_ERASE_CHECK */ } /* for (i) */ } /* else */ if (MSP430X == true) if (bslTxRx(BSL_MEMOFFSET, 0, (ushort)(0), null, blkin) != 0) return (error); } /* if ACTION_VERIFY | ACTION_ERASE_CHECK */ else if ((action & ACTION_ERASE_CHECK_FAST) != 0) /* FRGR 02/01 */ { error = Constants.ErrorNone; ; if (error != Constants.ErrorNone) return (error); error = bslTxRx(BSL_ECHECK, addr, len, null, blkin); //printf("Error: %i\n", error); if (error != Constants.ErrorNone) { return (ERR_ERASE_CHECK_FAILED); /* Erase Check failed! */ } } return (error); } public int signOff(int ERR_VERIFY_FAILED, bool xt) { return 1; } public int txPasswd2(string passwdFile) { int i; /* Send "standard" password to get access to protected functions. */ mainForm.textBoxStatus.AppendText("Transmit standard password...\r\n"); mainForm.textBoxStatus.Refresh(); /* Fill blkout with 0xff * (Flash is completely erased, the contents of all Flash cells is 0xff) */ for (i = 0; i < 0x1E; i++) { blkout[i] = 0xff; } blkout[30] = 0x00; blkout[31] = 0x40; if ( (bslTxRx(BSL_TXPWORD, /* Command: Transmit Password */ 0xffe0, /* Address of interupt vectors */ 0x0020, /* Number of bytes */ blkout, blkin) == ERR_BSL_SYNC)) { throw new System.IO.InvalidDataException(); } else { return 1; } } } }