/*---------------------------------------------------------------------Monitor.h * Author: Joseph Wayne Dumoulin, Donald Delmar Davis, Suspect Devices * * Liscence: "Simplified BSD License" * * Copyright (c) 2016, Donald Delmar Davis, Suspect Devices * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in thedocumentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------------- * The idea here is to create an automation freindly monitor protocol and debug * interface. Because this needs to be efficient (and flexible) I have chosen a * very simple interface which will access and may manipulate a devices public * variables. * * Basic Syntax for the monitor is * XXX[?!:] * where: * XXX is a 3 letter command or variable. * ! execute command or store value * ? get value * :<20 char timestamp>, value returned. * * keywords are described in keywords.h */ #include #include #include #include "Monitor.h" #include "Clock.h" /* * +1 is for the trailing null. */ const char keywords[((NKEYWORDS)*3)+1] = KEYWORDS; #define KWHELPLEN 26 char kwhelp[((NKEYWORDS+1) * KWHELPLEN)+1] = HELPTEXT; char updateBuffer[MAX_RETURN_VALUE]; //allocate this once use it often. actionptr actions[NKEYWORDS]; void Monitor::update(const char *data, const char *format, ...) { va_list blarg; updateBuffer[0]=data[0];updateBuffer[1]=data[1];updateBuffer[2]=data[2];updateBuffer[3]=':'; timeStamp(updateBuffer+4); updateBuffer[23]=POST_TIMESTAMP_DELIMETER; va_start(blarg, format); vsnprintf(updateBuffer+24, MAX_RETURN_VALUE-24, format, blarg); va_end(blarg); if (!commandMode()) { MONITOR_UART.println(updateBuffer); MONITOR_UART.flush(); } }; Monitor monitor; void Monitor::fatal(int newstate, const char *format, ...) { va_list blarg; update("FTL", format, blarg); va_end(blarg); //update("FTL","Fatal Error, New State = %s", soh, stateName(soh)); //maybe move this to setstate. //sendActionOut(); //stateChange(soh); }; void Monitor::debug(const char *format, ...) { va_list blarg; // if (_debugLevel >= SEV_DEBUG) update("DBG:", format, blarg); va_end(blarg); }; char * samd21m0psn(char * buffer) { // https://gist.github.com/mgk/c9ec87436d2d679e5d08 volatile uint32_t val1, val2, val3, val4; volatile uint32_t *ptr1 = (volatile uint32_t *)0x0080A00C; val1 = *ptr1; volatile uint32_t *ptr = (volatile uint32_t *)0x0080A040; val2 = *ptr; ptr++; val3 = *ptr; ptr++; val4 = *ptr; snprintf(buffer, MONITOR_SERIAL_NUMBER_CHARS ,"%8x%8x%8x%8x", val1, val2, val3, val4); } Monitor::Monitor() { _debugLevel=EEPROM_NOT_SET; samd21m0psn(this->_psn); /* * insure that all jump table pointers go somewhere */ int k; for (k=0;k=0 && ndxavailable() ){ // while( monitor.console->available() && commandBufferIndex < MAX_MONITOR_LINE_LENGTH && ((ch=monitor.console->read()) != '\n') && ch !='\r' ) { // commandBuffer[commandBufferIndex++] = isprint(ch)?ch:'*'; // monitor.console->flush(); // } monitor.debug("monitor run"); if( (&MONITOR_UART!=NULL) && MONITOR_UART.available() ){ while(MONITOR_UART.available() && commandBufferIndex < MAX_MONITOR_LINE_LENGTH && ((ch=MONITOR_UART.read()) != '\n') && ch !='\r' ) { commandBuffer[commandBufferIndex++] = isprint(ch)?ch:'*'; MONITOR_UART.flush(); } if (commandBufferIndex && ((ch=='\n')||(ch=='\r'))) { while (commandBufferIndex<4) { commandBuffer[commandBufferIndex++]='*';}; // things get questionable if there are less than 4 characters. commandBuffer[commandBufferIndex]='\0'; commandBufferIndex=0; gotLine=true; } } if (gotLine) { key[0]=toupper(commandBuffer[0]); key[1]=toupper(commandBuffer[1]); key[2]=toupper(commandBuffer[2]); action=commandBuffer[3]; arguments=commandBuffer+4; index=monitor.lookupIndex(key); if (index>=0&&index=0 && ndx #ifndef MAGIC_KEY #define MAGIC_KEY 0x7777 #endif #ifndef MAGIC_KEY_POS #define MAGIC_KEY_POS 0x0800 #endif void jump2bootloader(){ int16_t magic_key_pos = MAGIC_KEY_POS; *(uint16_t *)magic_key_pos = MAGIC_KEY; wdt_enable(WDTO_120MS); for(;;); } void reboot(){ int16_t magic_key_pos = MAGIC_KEY_POS; *(uint16_t *)magic_key_pos = 0; wdt_enable(WDTO_120MS); for(;;); } #endif