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 Microcontroller { private string filename; private MainForm mainForm; //Reference to The Main Form static int maxData = 240; //Keeps the Data Frame from overrunning private byte rxHeader = 0; private byte seqNo, reqNo; private int lastError; private int byteCtr = 0; 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; const byte BSL_SYNC = 0x80; Dictionary AllPorts; public SerialPort Port; public Microcontroller(MainForm parentForm) { mainForm = parentForm; filename = mainForm.filename; } public Dictionary CreatePorts(int UsablePorts, int StartingPortNumber) { int localStartingPortNumber = 21; int localUsablePorts = 5; AllPorts = new Dictionary(); for (int i = localStartingPortNumber; i < (localUsablePorts + localStartingPortNumber);i++) { string PortName = "Com" + i; AllPorts.Add(i, new SerialPort(PortName)); } return AllPorts; } public void InitializePorts() { try { if (Port.IsOpen == true) { Port.Close(); } //Port.DataReceived += new SerialDataReceivedEventHandler(_serialPort_DataReceived); Port.BaudRate = 9600; Port.Parity = Parity.Even; Port.DataBits = 8; Port.StopBits = StopBits.One; Port.DtrEnable = true; Port.RtsEnable = true; Port.ReadTimeout = 0; Port.WriteTimeout = 50; Port.WriteBufferSize = 512; Port.ReadBufferSize = 256; //seqNo = 0; //reqNo = 0; Port.ParityReplace = 0xff; Port.Open(); Port.DiscardInBuffer(); Port.DiscardOutBuffer(); } catch { } } public void BslReset(Boolean invokeBSL) { try { if (Port.IsOpen == true) { Port.Close(); } Port.Open(); SetRstPin(true,Port); SetTestPin(true,Port); System.Threading.Thread.Sleep(250); if (invokeBSL) { SetRstPin(false,Port); System.Threading.Thread.Sleep(10);/* TEST pin: GND */ SetTestPin(true,Port); System.Threading.Thread.Sleep(10);/* TEST pin: Vcc */ SetTestPin(false,Port); System.Threading.Thread.Sleep(10);/* TEST pin: GND */ SetTestPin(true,Port); System.Threading.Thread.Sleep(10); /* TEST pin: Vcc */ SetTestPin(false,Port); System.Threading.Thread.Sleep(10);/* TEST pin: GND */ SetRstPin(true,Port); System.Threading.Thread.Sleep(10);/* RST pin: Vcc */ SetTestPin(true,Port); /* TEST pin: GND */ } else { SetRstPin(false,Port); /* RST pin: GND */ System.Threading.Thread.Sleep(30); /* delays */ SetRstPin(true,Port); } System.Threading.Thread.Sleep(250); Port.DiscardInBuffer(); Port.DiscardOutBuffer(); mainForm.textBoxStatus.AppendText(Port.PortName + " is working\r\n"); } catch (Exception) { mainForm.textBoxStatus.AppendText(Port.PortName + " is not working\r\n"); } } public int MassErases() { try { BslTxRx(Constants.BSLMassErase, /* Command: Mass Erase */ 0xff00, /* Any address within flash memory. */ 0xa504, /* Required setting for mass erase! */ null, blkin); } catch (Exception) { mainForm.textBoxStatus.AppendText("Erase has Errors"); } return 1; } public int TransmitPassword()//Was txPassword { int i; for (i = 0; i < 0x20; i++) { blkout[i] = 0xff; } return (BslTxRx(Constants.BSLSendPassword, /* Command: Transmit Password */ 0xffe0, /* Address of interupt vectors */ 0x0020, /* Number of bytes */ blkout, blkin)); } public void SetTestPin(Boolean level,SerialPort Port)//Controls TEST pin (0: VCC; 1: GND) { if (level == true) { Port.RtsEnable = true; } else { Port.RtsEnable = false; } Port.RtsEnable = level ? Port.RtsEnable = true : Port.RtsEnable = false; } public void SetRstPin(Boolean level,SerialPort Port)//Controls RST/NMI pin (0: GND; 1: VCC) { if (level == true) { Port.DtrEnable = true; } else { Port.DtrEnable = false; } Port.DtrEnable = level ? Port.DtrEnable = true : Port.DtrEnable = false; } public int programBlk(uint addr, ushort len, uint action) { int error = Constants.ErrorNone; if ((action & Constants.ActionProgram) != 0) { mainForm.textBoxStatus.AppendText("Program starting at " + addr + " " + len + " bytes\r\n"); mainForm.textBoxStatus.Refresh(); /* Program block: */ error = BslTxRx(Constants.BSLTransmitBlock, addr, len, blkout, blkin); if (error != Constants.ErrorNone) { return (error); /* Cancel, if error (ACTION_VERIFY is skipped!) */ } } return (error); } public int ProgramFile(string filename) { /* Starting point for programming Flash Memory with the exe (txt) file *Calls ProgramTIText *Calls BSLTxRx */ mainForm.textBoxStatus.AppendText("Program" + filename + "\r\n"); if ((error = ProgramTIText(filename,Constants.ActionProgram)) !=Constants.ErrorNone) { mainForm.textBoxStatus.AppendText("Error Programing Microcontroller\r\n"); } 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 { Port.DiscardInBuffer(); ch[0] = BSL_SYNC; Port.ReadTimeout = 50; Port.Write(ch, 0, 1); chback = Port.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 = Port.BytesToRead; } while (((rxCount = Port.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) { } public int BslTxRx(byte cmd, uint addr, ushort len, byte[] blkout, byte[] blkin) { /*Creates Data Structure dataOut and makes sure there is an even amount of bytes * Then Copies dataOut into blkout. First 4 bytes are address (addr) and length (len) * installed in ComTxRx */ byte[] dataOut = new byte[Constants.MaxFrameSize]; ushort length = 4; if (cmd == Constants.BSLTransmitBlock) { if ((addr % 2) != 0) { addr--; Array.Copy(blkout, 1, blkout, 0, len); blkout[0] = 0xFF; len++; } if ((len % 2) != 0) { blkout[(len++)] = 0xFF; } } if (cmd == Constants.BSLReceiveBlock) { if ((addr % 2) != 0) { addr--; len++; } if ((len % 2) != 0) { len++; } } if ((cmd == Constants.BSLTransmitBlock) || (cmd == Constants.BSLSendPassword)) { length = (ushort)(len + 4); } 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) { Array.Copy(blkout, 0, dataOut, 4, len); } if (bslSync() != Constants.ErrorNone) { return (Constants.ErrorBSLSync); } ComTxRx(cmd, dataOut, (byte)length); if (blkin != null) { 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. */ { uint prolongFactor = Constants.DefaultProlong; byte[] txFrame = new byte[Constants.MaxFrameSize]; ushort checksum = 0; int k = 0; int errCtr = 0; byte rxNum = 0; int resentFrame = 0; /* Transmitting part ----------------------------------------*/ if ((length % 2) != 0) { dataOut[length++] = 0xFF; // fill with 0xFF } txFrame[0] = (byte)(Constants.DataFrame | seqNo); txFrame[1] = cmd; txFrame[2] = length; txFrame[3] = length; reqNo = (byte)((seqNo + 1) % Constants.MaxFrameCount); Array.Copy(dataOut, 0, txFrame, 4, length); checksum = CalcChecksum(txFrame, (ushort)(length + 4)); txFrame[length + 4] = (byte)(checksum); txFrame[length + 5] = (byte)(checksum >> 8); /* Transmit data:-------------------------------------------- */ k = 0; /* Clear receiving queue: */ Port.DiscardInBuffer(); Array.Clear(blkin, 0, 250); do { Port.Write(txFrame, k++, 1); } while (k < length + 6); /* 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; lastError = Constants.ErrorNone; /* Acknowledge received correctly => next frame */ } break; /* case DATA_ACK */ case Constants.DataNAN: lastError =Constants.ErrorRxNak; break; /* case DATA_NAK */ case Constants.DataFrame: if (rxNum == reqNo) if (ComRxFrame(rxHeader, rxNum) == 0) lastError = Constants.ErrorNone; break; /* case DATA_FRAME */ case Constants.CommandFailed: /* Frame ok, but command failed. */ lastError = Constants.ErrorCmdFailed; 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 == Constants.ErrorCmdNotCompleted) { /* Accept QUERY_RESPONSE as real ACK and correct Seq.-No.: */ seqNo = reqNo; } if (lastError == Constants.ErrorNone) return (lastError = Constants.ErrorCom); else return (lastError); } /* comTxRx */ public int ComRxFrame(byte rxHeader, byte rxNum) { ushort checksum; byte rxLength; ushort rxLengthCRC; int x = 0; rxFrame[0] = (byte)(Constants.DataFrame | rxNum); if (comWaitForData(3, timeout) >= 3) { Port.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); Port.Read(rxFrame, 4, rxLengthCRC); x = Port.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 (Constants.ErrorCom); /* Frame has errors! */ } /* comRxFrame */ public int ComRxHeader(ref byte rxHeader, byte rxNum, uint timeout) { byte[] Hdr = new byte[1]; if (comWaitForData(1, timeout) >= 1) { Port.Read(Hdr, 0, 1); rxHeader = (byte)(Hdr[0] & 0xf0); rxNum = (byte)(Hdr[0] & 0x0f); reqNo = 0; seqNo = 0; rxNum = 0; return (Constants.ErrorNone); } else { rxHeader = 0; rxNum = 0; return (lastError = Constants.ErrorRxHdrTimeout); } } 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)); 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