Embedded RTOS class project. This project allows a Python/Tk program running on a PC host to monitor/control a test-CPU programmed into an altera development board.
Dependencies: C12832_lcd USBDevice mbed-rtos mbed mmSPI-2 watchdog
Fork of USB_device_project by
Revision 13:7e1688393abc, committed 2013-09-17
- Comitter:
- gatedClock
- Date:
- Tue Sep 17 19:07:00 2013 +0000
- Parent:
- 11:480f06885f0f
- Child:
- 14:7a310276b8b9
- Commit message:
- updates for RTOS class project.
Changed in this revision
--- a/main.cpp Sun Sep 01 20:36:16 2013 +0000
+++ b/main.cpp Tue Sep 17 19:07:00 2013 +0000
@@ -1,14 +1,34 @@
/*----------------------------------------------//------------------------------
student : m-moore
email : gated.clock@gmail.com
- class : usb device drivers
+ class : embedded RTOS
directory : USB_device_project
file : main.cpp
- date : september 3, 2013.
+ date : september 19, 2013.
----copyright-----------------------------------//------------------------------
licensed for personal and academic use.
- commercial use must be approved by the account-holder of
+ commercial use of original code must be approved by the account-holder of
gated.clock@gmail.com
+----revision------------------------------------//------------------------------
+ this is the embedded RTOS class revision.
+ changes made since the USB device class release:
+
+ 1. a 'read all registers' feature has been added, which speeds up
+ CPU execution, since the UI obtains all of the register states after
+ each CPU clock. originally, each register was individually read.
+ now, all registers are read at once, if so requested by the python code.
+
+ 2. some 'if' statements were changed to 'switch' statements (neatening).
+
+ 3. added watchdog timers for the three threads. this via a meta-watchdog thread.
+
+ 4. added #defined-based option to either boot on error detection
+ (such as malloc fail) or use error(); function.
+
+ 5. the LCD is updated only if a display value is changed - reduced power
+ usage a little & reduces potential 'blinkieness'.
+
+ 6. BOOT notification on LCD.
----description---------------------------------//------------------------------
overview:
program to provide round-trip communication between a python test-control
@@ -23,14 +43,15 @@
4. main thread provides USBSerial communication to/from host.
5. SPI processing thread provides SPI communication to/from DUT.
6. mmSPI library generates non-overlapping SPI and CPU clocks.
- 7. background diagnostic thread provides LCD & LED updates.
+ 7. background diagnostic thread provides LCD & error updates.
+ 8. meta watchdog thread monitors itself & the other threads.
indicators: (led<3:0> = LED<1:4>)
1. LCD provides running counts for SPI and CPU clock cycles.
- 2. led0 indicates main thread processing.
- 3. led1 indicates SPI thread processing.
- 4. led2 indicates LCD thread processing.
- 5. led3 indicates reply-to-host underflow (should never turn on).
+ 2. led0 indicates main thread processing.
+ 3. led1 indicates SPI thread processing.
+ 4. led2 indicates LCD thread processing.
+ 5. led3 indicates watchdog thread processing.
implementation:
1. main.processIncomingSerial(): accept incoming serial data from host,
@@ -56,6 +77,8 @@
connection.
5. no particular power sequence is needed for this system to work.
+ timing critical path: serial processing. the python code needs
+ a delay between serial access of 40mS conservatively.
testing:
the python UI provides the main testing mechanism.
@@ -113,18 +136,22 @@
#include "C12832_lcd.h" // LCD display.
#include "rtos.h" // RTOS.
#include "mmSPI.h" // SPI.
+ #include "watchdog.h" // watchdog.
//---defines------------------------------------//------------------------------
#define LCD1 lcd.locate(0, 0); // LCD line 1.
#define LCD2 lcd.locate(0,11); // LCD line 2.
#define LCD3 lcd.locate(0,22); // LCD line 3.
#define LCD3 lcd.locate(0,22); // LCD line 3.
+ #define WATCHDOG_S 10 // watchdog timeout, in seconds.
+ #define ERROR_BOOT 1 // 1 means boot rather than error().
#define SPI_BYTES 8 // number of SPI bytes.
#define SPI_HZ 100000 // SPI frequency in Hz.
- #define SER_BYTES 8 // serial in/out # of bytes.
+ #define SER_BYTES 18 // serial in/out # of bytes.
#define SER_ALIGN 7 // '$' location in shift-register.
#define THREAD_0_WAIT 8 // multitasking wait mS.
#define THREAD_1_WAIT 2 // multitasking wait mS.
#define THREAD_2_WAIT 128 // multitasking wait mS.
+ #define THREAD_3_WAIT 128 // multitasking wait mS.
#define HB_MODULO 64 // heartbeat slowdown factor.
#define POOL_LEN 16 // memory pool dimension.
#define HCMD_SETREG 1 // host command 'set register'.
@@ -133,6 +160,7 @@
#define HCMD_GETMM 4 // host command 'get main-memory.'
#define HCMD_STEP 5 // host command 'step-CPU'.
#define HCMD_SETIR 6 // host command 'set-IR'.
+ #define HCMD_GETALLREG 7 // host command 'get-all-registers'.
#define CPU_REG_0 0 // CPU register 0.
#define CPU_REG_1 1 // CPU register 1.
#define CPU_REG_2 2 // CPU register 2.
@@ -140,6 +168,8 @@
#define CPU_REG_PC 4 // CPU Program Counter.
#define CPU_IR_H 5 // CPU IR high-byte.
#define CPU_IR_L 6 // CPU IR low-byte.
+//--externals-----------------------------------//------------------------------
+ extern "C" void mbed_reset(); // processor reset.
//--global_definitions--------------------------//------------------------------
struct tFromHost // command from host.
{
@@ -164,10 +194,21 @@
char cRegisterValue; // data from CPU register.
char cMMaddress; // which MM address read.
char cMMdataH; // MM content high byte.
- char cMMdataL; // MM content low byte.
+ char cMMdataL; // MM content low byte.
+ char cReg0; // data from R0.
+ char cReg1; // data from R1.
+ char cReg2; // data from R2.
+ char cReg3; // data from R3.
+ char cPC; // data from program counter.
+ char cIRH; // high byte from instruction register.
+ char cIRL; // low byte from instruction register.
};
MemoryPool<tToHost, POOL_LEN> mPoolToHost;
Queue <tToHost, POOL_LEN> qToHost;
+
+ Queue<int, POOL_LEN> queueWatchdogThread_0; // main thread watchdog notice.
+ Queue<int, POOL_LEN> queueWatchdogThread_1; // thread 1 watchdog notice.
+ Queue<int, POOL_LEN> queueWatchdogThread_2; // thread 2 watchdog notice.
//--global_variables----------------------------//------------------------------
char gpcSerialFromHost[SER_BYTES]; // incoming serial buffer.
char gpcSerialToHost [SER_BYTES]; // outgoing serial buffer.
@@ -189,7 +230,8 @@
void processIncomingSerial(); // process incoming host data.
void processOutgoingSerial(); // process outgoing data to host.
void SPIprocessingThread(void const *args); // SPI-side processing.
- void diagnosticThread (void const *args); // LCD and LED notifications.
+ void diagnosticThread (void const *args); // LCD and LED notifications.
+ void watchdogThread (void const *args); // overall watchdog.
char ascii_nibble_to_binary(char cAscii); // ascii nibble -> binary.
char binary_to_ascii_nibble(char cBinary); // binary -> ascii nibble.
void clear_tFromHost(tFromHost *ptFromHost);// initialize structure.
@@ -205,8 +247,15 @@
gdRoundTrip = 1024; // initialize global.
gulSPIclkCount = 0; // initialize global.
gulCPUclkCount = 0; // initialize global.
+ led0 = 0; // initialize global.
+ led1 = 0; // initialize global.
+ led2 = 0; // initialize global.
+ led3 = 0; // initialize global.
dHeartbeat = 0; // initialize local.
dLoop = 0; // initialize local.
+
+ // BOOT notification.
+ lcd.cls(); LCD2; lcd.printf(" BOOT"); wait(1.0);
// initialize serial-in shift-register.
for (dLoop = 0; dLoop < SER_BYTES; dLoop++) gpcSerialFromHost[dLoop] = 0;
@@ -215,8 +264,11 @@
Thread thread_1(SPIprocessingThread,NULL,osPriorityHigh,DEFAULT_STACK_SIZE,NULL);
// thread-out diagnostics.
- Thread thread_2(diagnosticThread,NULL,osPriorityIdle,DEFAULT_STACK_SIZE,NULL);
-
+ Thread thread_2(diagnosticThread, NULL,osPriorityIdle,DEFAULT_STACK_SIZE,NULL);
+
+ // thread-out universal watchdog.
+ Thread thread_3(watchdogThread, NULL,osPriorityIdle,DEFAULT_STACK_SIZE,NULL);
+
while(1) // main loop.
{
processIncomingSerial(); // process data in from host.
@@ -224,7 +276,8 @@
dHeartbeat++; // thread heartbeat.
if (!(dHeartbeat % HB_MODULO)) led0 = !led0;
- Thread::wait(THREAD_0_WAIT); // multitasking.
+ queueWatchdogThread_0.put((int *) 0,1); // adds 1mS to wait.
+ Thread::wait(THREAD_0_WAIT - 1); // multitasking.
} // main loop.
} // main.
/*----------------------------------------------//----------------------------*/
@@ -316,43 +369,92 @@
if (gcNewCommand) // execute once per new command.
{
pFromHost = mPoolFromHost.alloc(); // allocate next pool entry.
- if (!pFromHost) error("\n\r processIncomingSerial : FATAL malloc error for pFromHost. \n\r");
+ if (!pFromHost) // failure detection.
+ {
+ if (ERROR_BOOT) mbed_reset(); else
+ error("\n\r processIncomingSerial : FATAL malloc error for pFromHost. \n\r");
+ }
+
clear_tFromHost(pFromHost); // initialize structure.
// copy-in host message.
pFromHost->cCommand = ascii_nibble_to_binary(gpcSerialFromHost[0]);
-
- // host requests register access.
- if (pFromHost->cCommand == HCMD_SETREG || pFromHost->cCommand == HCMD_GETREG)
- {
- pFromHost->cRegisterID = ascii_nibble_to_binary(gpcSerialFromHost[1]);
- pFromHost->cRegisterValue = ((ascii_nibble_to_binary(gpcSerialFromHost[2])) << 4) +
- ascii_nibble_to_binary(gpcSerialFromHost[3]);
- }
-
- if (pFromHost->cCommand == HCMD_SETIR) // host requests IR write.
+//----
+
+ switch(pFromHost->cCommand) // command dependency.
{
- pFromHost->cIRValueH = ((ascii_nibble_to_binary(gpcSerialFromHost[2])) << 4) +
- ascii_nibble_to_binary(gpcSerialFromHost[3]);
- pFromHost->cIRValueL = ((ascii_nibble_to_binary(gpcSerialFromHost[4])) << 4) +
- ascii_nibble_to_binary(gpcSerialFromHost[5]);
- }
-
+ case HCMD_SETREG : // host command 'set register'.
+ {
+ pFromHost->cRegisterID = ascii_nibble_to_binary(gpcSerialFromHost[1]);
+ pFromHost->cRegisterValue = ((ascii_nibble_to_binary(gpcSerialFromHost[2])) << 4) +
+ ascii_nibble_to_binary(gpcSerialFromHost[3]);
+ break;
+ } // host command 'set register'.
- // host requests main-memory access.
- if (pFromHost->cCommand == HCMD_SETMM || pFromHost->cCommand == HCMD_GETMM)
- {
- pFromHost->cMMaddress = ((ascii_nibble_to_binary(gpcSerialFromHost[1])) << 4) +
- ascii_nibble_to_binary(gpcSerialFromHost[2]);
- pFromHost->cMMdataH = ((ascii_nibble_to_binary(gpcSerialFromHost[3])) << 4) +
- ascii_nibble_to_binary(gpcSerialFromHost[4]);
- pFromHost->cMMdataL = ((ascii_nibble_to_binary(gpcSerialFromHost[5])) << 4) +
- ascii_nibble_to_binary(gpcSerialFromHost[6]);
- } // host requests main-memory access.
+ case HCMD_GETREG : // host command 'get register'.
+ {
+ pFromHost->cRegisterID = ascii_nibble_to_binary(gpcSerialFromHost[1]);
+ pFromHost->cRegisterValue = ((ascii_nibble_to_binary(gpcSerialFromHost[2])) << 4) +
+ ascii_nibble_to_binary(gpcSerialFromHost[3]);
+ gdRoundTrip++; // expected reply to host is pending.
+ break;
+ } // host command 'get register'.
+
+ case HCMD_SETMM : // host command 'set main-memory.'
+ {
+ pFromHost->cMMaddress = ((ascii_nibble_to_binary(gpcSerialFromHost[1])) << 4) +
+ ascii_nibble_to_binary(gpcSerialFromHost[2]);
+ pFromHost->cMMdataH = ((ascii_nibble_to_binary(gpcSerialFromHost[3])) << 4) +
+ ascii_nibble_to_binary(gpcSerialFromHost[4]);
+ pFromHost->cMMdataL = ((ascii_nibble_to_binary(gpcSerialFromHost[5])) << 4) +
+ ascii_nibble_to_binary(gpcSerialFromHost[6]);
+ break;
+ } // host command 'set main-memory.'
+
+ case HCMD_GETMM : // host command 'get main-memory.'
+ {
+ pFromHost->cMMaddress = ((ascii_nibble_to_binary(gpcSerialFromHost[1])) << 4) +
+ ascii_nibble_to_binary(gpcSerialFromHost[2]);
+ pFromHost->cMMdataH = ((ascii_nibble_to_binary(gpcSerialFromHost[3])) << 4) +
+ ascii_nibble_to_binary(gpcSerialFromHost[4]);
+ pFromHost->cMMdataL = ((ascii_nibble_to_binary(gpcSerialFromHost[5])) << 4) +
+ ascii_nibble_to_binary(gpcSerialFromHost[6]);
+
+ gdRoundTrip++; // expected reply to host is pending.
+ break;
+ } // host command 'get main-memory.'
+
+ case HCMD_STEP : // host command 'step-CPU'.
+ {
+ break;
+ } // host command 'step-CPU'.
+
+ case HCMD_SETIR : // host command 'set-IR'.
+ {
+ pFromHost->cIRValueH = ((ascii_nibble_to_binary(gpcSerialFromHost[2])) << 4) +
+ ascii_nibble_to_binary(gpcSerialFromHost[3]);
+ pFromHost->cIRValueL = ((ascii_nibble_to_binary(gpcSerialFromHost[4])) << 4) +
+ ascii_nibble_to_binary(gpcSerialFromHost[5]);
+ break;
+ } // host command 'set-IR'.
+
+ case HCMD_GETALLREG : // host command 'get-all-registers'.
+ {
+ gdRoundTrip++; // expected reply to host is pending.
+ break;
+ } // host command 'get-all-registers'.
- if (pFromHost->cCommand == HCMD_GETREG || pFromHost->cCommand == HCMD_GETMM)
- gdRoundTrip++; // expected reply to host is pending.
+ default : // default.
+ {
+ if (ERROR_BOOT) mbed_reset(); else
+ error("\n\r processIncomingSerial : ERROR unrecognised command from host. \n\r");
+ break;
+ } // default.
+ } // command dependency.
+
+//----
+
qFromHost.put(pFromHost); // send out for processing.
gcNewCommand = 0; // don't execute until next new command.
} // execute once per new command.
@@ -370,43 +472,101 @@
{
// bring it in from the queue.
gpToHost = (tToHost *) gqToHostEvent.value.p;
- if (!gpToHost) error("\n\r processOutgoingSerial : FATAL NULL gpToHost pointer. \n\r");
+ if (!gpToHost) // failure detection.
+ {
+ if (ERROR_BOOT) mbed_reset(); else
+ error("\n\r processOutgoingSerial : FATAL NULL gpToHost pointer. \n\r");
+ }
// clear outgoing buffer.
for (dLoop = 0; dLoop < SER_BYTES; dLoop++) gpcSerialToHost[dLoop] = 0;
-
- // the commands from the host were
- // looped-back into the to-host struct,
- // make use of them here.
-
- if (gpToHost->cCommand == HCMD_GETREG) // reading from a register.
+
+ switch(gpToHost->cCommand) // the from-host command was looped to here.
{
- gpcSerialToHost[0] = binary_to_ascii_nibble( gpToHost->cCommand);
- gpcSerialToHost[1] = binary_to_ascii_nibble( gpToHost->cRegisterID);
- gpcSerialToHost[2] = binary_to_ascii_nibble(((gpToHost->cRegisterValue) >> 4) & 0x0F);
- gpcSerialToHost[3] = binary_to_ascii_nibble(((gpToHost->cRegisterValue) >> 0) & 0x0F);
- gpcSerialToHost[4] = '\n'; // signals end of transfer.
+ case HCMD_SETREG : // host command 'set register'.
+ {
+ break;
+ } // host command 'set register'.
+
+ case HCMD_GETREG : // host command 'get register'.
+ {
+ gpcSerialToHost[0] = binary_to_ascii_nibble( gpToHost->cCommand);
+ gpcSerialToHost[1] = binary_to_ascii_nibble( gpToHost->cRegisterID);
+ gpcSerialToHost[2] = binary_to_ascii_nibble(((gpToHost->cRegisterValue) >> 4) & 0x0F);
+ gpcSerialToHost[3] = binary_to_ascii_nibble(((gpToHost->cRegisterValue) >> 0) & 0x0F);
+ gpcSerialToHost[4] = '\n'; // signals end of transfer.
+
+ // transmit to the host.
+ serial.writeBlock((uint8_t *) gpcSerialToHost, (uint16_t) SER_BYTES);
+ gdRoundTrip--; // expected reply sent to host.
+ break;
+ } // host command 'get register'.
+
+ case HCMD_SETMM : // host command 'set main-memory.'
+ {
+ break;
+ } // host command 'set main-memory.'
+
+ case HCMD_GETMM : // host command 'get main-memory.'
+ {
+ gpcSerialToHost[0] = binary_to_ascii_nibble( gpToHost->cCommand);
+ gpcSerialToHost[1] = binary_to_ascii_nibble(((gpToHost->cMMaddress) >> 4) & 0x0F);
+ gpcSerialToHost[2] = binary_to_ascii_nibble(((gpToHost->cMMaddress) >> 0) & 0x0F);
+ gpcSerialToHost[3] = binary_to_ascii_nibble(((gpToHost->cMMdataH ) >> 4) & 0x0F);
+ gpcSerialToHost[4] = binary_to_ascii_nibble(((gpToHost->cMMdataH ) >> 0) & 0x0F);
+ gpcSerialToHost[5] = binary_to_ascii_nibble(((gpToHost->cMMdataL ) >> 4) & 0x0F);
+ gpcSerialToHost[6] = binary_to_ascii_nibble(((gpToHost->cMMdataL ) >> 0) & 0x0F);
+ gpcSerialToHost[7] = '\n'; // signals end of transfer.
// transmit to the host.
- serial.writeBlock((uint8_t *) gpcSerialToHost, (uint16_t) SER_BYTES);
- gdRoundTrip--; // expected reply sent to host.
- }
-
- if (gpToHost->cCommand == HCMD_GETMM) // reading from main-memory.
- {
- gpcSerialToHost[0] = binary_to_ascii_nibble( gpToHost->cCommand);
- gpcSerialToHost[1] = binary_to_ascii_nibble(((gpToHost->cMMaddress) >> 4) & 0x0F);
- gpcSerialToHost[2] = binary_to_ascii_nibble(((gpToHost->cMMaddress) >> 0) & 0x0F);
- gpcSerialToHost[3] = binary_to_ascii_nibble(((gpToHost->cMMdataH ) >> 4) & 0x0F);
- gpcSerialToHost[4] = binary_to_ascii_nibble(((gpToHost->cMMdataH ) >> 0) & 0x0F);
- gpcSerialToHost[5] = binary_to_ascii_nibble(((gpToHost->cMMdataL ) >> 4) & 0x0F);
- gpcSerialToHost[6] = binary_to_ascii_nibble(((gpToHost->cMMdataL ) >> 0) & 0x0F);
- gpcSerialToHost[7] = '\n'; // signals end of transfer.
-
+ serial.writeBlock((uint8_t *) gpcSerialToHost, (uint16_t) SER_BYTES);
+ gdRoundTrip--; // expected reply sent to host.
+ break;
+ } // host command 'get main-memory.'
+
+ case HCMD_STEP : // host command 'step-CPU'.
+ {
+ break;
+ } // host command 'step-CPU'.
+
+ case HCMD_SETIR : // host command 'set-IR'.
+ {
+ break;
+ } // host command 'set-IR'.
+
+ case HCMD_GETALLREG : // host command 'get-all-registers'.
+ {
+ gpcSerialToHost[ 0] = binary_to_ascii_nibble( gpToHost->cCommand);
+ gpcSerialToHost[ 1] = binary_to_ascii_nibble(((gpToHost->cReg0) >> 4) & 0x0F);
+ gpcSerialToHost[ 2] = binary_to_ascii_nibble(((gpToHost->cReg0) >> 0) & 0x0F);
+ gpcSerialToHost[ 3] = binary_to_ascii_nibble(((gpToHost->cReg1) >> 4) & 0x0F);
+ gpcSerialToHost[ 4] = binary_to_ascii_nibble(((gpToHost->cReg1) >> 0) & 0x0F);
+ gpcSerialToHost[ 5] = binary_to_ascii_nibble(((gpToHost->cReg2) >> 4) & 0x0F);
+ gpcSerialToHost[ 6] = binary_to_ascii_nibble(((gpToHost->cReg2) >> 0) & 0x0F);
+ gpcSerialToHost[ 7] = binary_to_ascii_nibble(((gpToHost->cReg3) >> 4) & 0x0F);
+ gpcSerialToHost[ 8] = binary_to_ascii_nibble(((gpToHost->cReg3) >> 0) & 0x0F);
+ gpcSerialToHost[ 9] = binary_to_ascii_nibble(((gpToHost->cPC) >> 4) & 0x0F);
+ gpcSerialToHost[10] = binary_to_ascii_nibble(((gpToHost->cPC) >> 0) & 0x0F);
+ gpcSerialToHost[11] = binary_to_ascii_nibble(((gpToHost->cIRH) >> 4) & 0x0F);
+ gpcSerialToHost[12] = binary_to_ascii_nibble(((gpToHost->cIRH) >> 0) & 0x0F);
+ gpcSerialToHost[13] = binary_to_ascii_nibble(((gpToHost->cIRL) >> 4) & 0x0F);
+ gpcSerialToHost[14] = binary_to_ascii_nibble(((gpToHost->cIRL) >> 0) & 0x0F);
+ gpcSerialToHost[15] = '\n'; // signals end of transfer.
+
// transmit to the host.
- serial.writeBlock((uint8_t *) gpcSerialToHost, (uint16_t) SER_BYTES);
- gdRoundTrip--; // expected reply sent to host.
- }
+ serial.writeBlock((uint8_t *) gpcSerialToHost, (uint16_t) SER_BYTES);
+ gdRoundTrip--; // expected reply sent to host.
+ break;
+ } // host command 'get-all-registers'.
+
+ default :
+ {
+ if (ERROR_BOOT) mbed_reset(); else
+ error("\n\r processOutgoingSerial : ERROR unrecognised command from host. \n\r");
+ break;
+ } // default.
+ } // switch(gpToHost->cCommand)
+
mPoolToHost.free(gpToHost); // done with this queue entry.
gpToHost = NULL; // clear pointer.
} // if new reply to host.
@@ -421,6 +581,7 @@
{
char pcSendBuffer [SPI_BYTES]; // SPI send buffer.
char pcReceiveBuffer[SPI_BYTES]; // SPI receive buffer.
+ char pcRegisters [SPI_BYTES]; // fetch-all-registers vector.
int dHeartbeat; // heartbeat counter.
int dMemoryRead; // read main-memory into this.
int dLoop; // loop index.
@@ -439,8 +600,12 @@
for (dLoop = 0; dLoop < SPI_BYTES; dLoop++) pcSendBuffer [dLoop] = 0;
for (dLoop = 0; dLoop < SPI_BYTES; dLoop++) pcReceiveBuffer[dLoop] = 0;
- pSPI = new mmSPI; // SPI allocation.
- if (!pSPI) error("\n\r SPIprocessingThread : FATAL new error for pSPI. \n\r");
+ pSPI = new mmSPI; // SPI allocation.
+ if (!pSPI) // failure detection.
+ {
+ if (ERROR_BOOT) mbed_reset(); else
+ error("\n\r SPIprocessingThread : FATAL new error for pSPI. \n\r");
+ }
pSPI->setSendBuffer (pcSendBuffer); // set SPI send buffer.
pSPI->setReceiveBuffer(pcReceiveBuffer); // set SPI receive buffer.
@@ -456,7 +621,11 @@
{
// bring it in from the queue.
pFromHost = (tFromHost *) qFromHostEvent.value.p;
- if (!pFromHost) error("\n\r SPIprocessingThread : FATAL NULL pFromHost pointer. \n\r");
+ if (!pFromHost) // failure detection.
+ {
+ if (ERROR_BOOT) mbed_reset(); else
+ error("\n\r SPIprocessingThread : FATAL NULL pFromHost pointer. \n\r");
+ }
switch(pFromHost->cCommand) // host command decode.
{
@@ -483,7 +652,12 @@
case HCMD_GETREG : // get CPU register.
{
gpToHost = mPoolToHost.alloc(); // allocate next pool entry.
- if (!gpToHost) error("\n\r SPIprocessingThread : FATAL malloc error for gpToHost. \n\r");
+ if (!gpToHost) // failure detection.
+ {
+ if (ERROR_BOOT) mbed_reset(); else
+ error("\n\r SPIprocessingThread : FATAL malloc error for gpToHost. \n\r");
+ }
+
clear_tToHost(gpToHost); // initialize structure.
switch(pFromHost->cRegisterID) // which register to read from.
@@ -506,6 +680,35 @@
break;
} // get CPU register.
+ case HCMD_GETALLREG : // get all CPU registers.
+ {
+ gpToHost = mPoolToHost.alloc(); // allocate next pool entry.
+ if (!gpToHost) // failure detection.
+ {
+ if (ERROR_BOOT) mbed_reset(); else
+ error("\n\r SPIprocessingThread : FATAL malloc error for gpToHost. \n\r");
+ }
+
+ clear_tToHost(gpToHost); // initialize structure.
+
+ // tell SPI to return all reg content.
+ pSPI->read_all_registers(pcRegisters);
+
+ gpToHost->cReg0 = pcRegisters[6]; // transfer to outgoing structure.
+ gpToHost->cReg1 = pcRegisters[5];
+ gpToHost->cReg2 = pcRegisters[4];
+ gpToHost->cReg3 = pcRegisters[3];
+ gpToHost->cPC = pcRegisters[2];
+ gpToHost->cIRH = pcRegisters[1];
+ gpToHost->cIRL = pcRegisters[0];
+
+ // loop-back to host.
+ gpToHost->cCommand = pFromHost->cCommand;
+ qToHost.put(gpToHost); // send up for processing.
+
+ break;
+ } // get all CPU registers.
+
case HCMD_SETMM : // do main-memory write.
{
pSPI->write_memory(pFromHost->cMMdataH, pFromHost->cMMdataL, pFromHost->cMMaddress);
@@ -514,8 +717,13 @@
case HCMD_GETMM : // do main-memory read.
{
- gpToHost = mPoolToHost.alloc(); // allocate next pool entry.
- if (!gpToHost) error("\n\r SPIprocessingThread : FATAL malloc error for gpToHost. \n\r");
+ gpToHost = mPoolToHost.alloc(); // allocate next pool entry.
+ if (!gpToHost) // failure detection.
+ {
+ if (ERROR_BOOT) mbed_reset(); else
+ error("\n\r SPIprocessingThread : FATAL malloc error for gpToHost. \n\r");
+ }
+
clear_tToHost(gpToHost); // initialize structure.
// read from CPU memory.
@@ -547,39 +755,85 @@
// thread heartbeat.
dHeartbeat++; if (!(dHeartbeat % HB_MODULO)) led1 = !led1;
- Thread::wait(THREAD_1_WAIT); // cooperative multitasking.
+ queueWatchdogThread_1.put((int *) 0,1); // adds 1mS to wait.
+ Thread::wait(THREAD_1_WAIT - 1); // cooperative multitasking.
} // thread loop.
} // SPIprocessingThread.
/*----------------------------------------------//----------------------------*/
- void diagnosticThread(void const *args) // LCD and LED notifications.
+ void diagnosticThread(void const *args) // LCD notification & error check.
{
- int dHeartbeat; // heartbeat counter.
-
+ // track previous values.
+ static unsigned long ulLastSPIclkCount = 1;
+ static unsigned long ulLastCPUclkCount = 1;
+ int dHeartbeat; // heartbeat counter.
+
dHeartbeat = 0; // initialize.
- led3 = 0; // initialize.
-
+
while(1) // thread loop.
{
// if message round trip
// count not consistent.
- if (gdRoundTrip > 1025 || gdRoundTrip < 1024) led3 = 1;
-
- lcd.cls(); // clear LCD display.
- LCD1; // lcd line 1.
- lcd.printf(" USB DEV CLASS PROJECT");
+ if (gdRoundTrip > 1025 || gdRoundTrip < 1024)
+ {
+ if (ERROR_BOOT) mbed_reset(); else
+ error("\n\r diagnosticThread : ERROR serial reply underflow. \n\r");
+ }
- LCD2; // lcd line 2.
- lcd.printf(" %11lu = SPI clocks",gulSPIclkCount);
+ // update LCD only if a display
+ // value has changed. anti-blink,
+ // save a bit of power.
+ if (gulSPIclkCount != ulLastSPIclkCount ||
+ gulCPUclkCount != ulLastCPUclkCount )
+ {
+ lcd.cls(); // clear LCD display.
+ LCD1; // lcd line 1.
+ lcd.printf(" RTOS CLASS PROJECT");
- LCD3; // lcd line 3.
- lcd.printf(" %11lu = CPU clocks",gulCPUclkCount);
+ LCD2; // lcd line 2.
+ lcd.printf(" %11lu = SPI clocks",gulSPIclkCount);
+
+ LCD3; // lcd line 3.
+ lcd.printf(" %11lu = CPU clocks",gulCPUclkCount);
+ }
+
+ ulLastSPIclkCount = gulSPIclkCount; // pipeline.
+ ulLastCPUclkCount = gulCPUclkCount; // pipeline.
dHeartbeat++; // thread heartbeat.
if (!(dHeartbeat % HB_MODULO)) led2 = !led2;
- Thread::wait(THREAD_2_WAIT); // multitasking.
+ queueWatchdogThread_2.put((int *) 0,1); // adds 1mS to wait.
+ Thread::wait(THREAD_2_WAIT - 1); // multitasking.
} // thread loop.
} // diagnosticThread.
/*----------------------------------------------//----------------------------*/
+ // this is its own watchdog.
+
+ void watchdogThread(void const *args) // overall watchdog.
+ {
+ int dHeartbeat; // heartbeat counter.
+ osEvent queueEvent; // queue event
+ Watchdog watchdog; // the one and only watchdog.
+
+ dHeartbeat = 0; // initialize.
+
+ watchdog.kick(WATCHDOG_S); // initialize watchdog.
+
+ while (1) // thread loop.
+ {
+ // all other threads report-in.
+ // blocking wait on all of them.
+ queueEvent = queueWatchdogThread_0.get(osWaitForever);
+ queueEvent = queueWatchdogThread_1.get(osWaitForever);
+ queueEvent = queueWatchdogThread_2.get(osWaitForever);
+
+ watchdog.kick(); // reset watchdog timer.
+
+ dHeartbeat++; // thread heartbeat.
+ if (!(dHeartbeat % HB_MODULO)) led3 = !led3;
+ Thread::wait(THREAD_3_WAIT); // multitasking.
+ } // thread loop.
+ }
+/*----------------------------------------------//----------------------------*/
char ascii_nibble_to_binary(char cAscii) // ascii nibble -> binary.
{
char cBinary; // converted value.
--- a/mmPython/mmUI.txt Sun Sep 01 20:36:16 2013 +0000
+++ b/mmPython/mmUI.txt Tue Sep 17 19:07:00 2013 +0000
@@ -75,7 +75,7 @@
self.__isRunning = 0 # program execution not running.
self.__testRunning = 0 # test mode not runing.
self.__testIter = 0 # test mode iteration count.
- self.__sleepVal = 0.04 # serial transceive sleep.
+ self.__sleepVal = 0.04 # serial transceive sleep. 3 works.
self.uiR0 (0, 1, 10) # label/entry widgets (x, y, width)
@@ -294,58 +294,35 @@
def selectRegReadButtonPressed(self): # REG READ button has been pressed.
self.refreshUI() # ensure proper text formats.
+ # real all registers.
+ self.__iUSB.write(self.buildReadAllRegisterCommand())
+ messageVector = self.__iUSB.read()
- # read R0.
- self.__iUSB.write(self.buildReadRegisterCommand("0"))
- fetchTextR0 = self.__iUSB.read()
- hexTextR0 = self.formatRegValPayload(fetchTextR0)
- self.__R0Entry.delete(0,99)
+ # parse-out the register entries.
+ hexTextR0 = "0x" + messageVector[ 1: 3]
+ hexTextR1 = "0x" + messageVector[ 3: 5]
+ hexTextR2 = "0x" + messageVector[ 5: 7]
+ hexTextR3 = "0x" + messageVector[ 7: 9]
+ hexTextPC = "0x" + messageVector[ 9:11]
+ hexTextIR = "0x" + messageVector[11:15]
+
+
+ self.__R0Entry.delete(0,99) # R0 to UI.
self.__R0Entry.insert(0,hexTextR0)
- # read R1.
- self.__iUSB.write(self.buildReadRegisterCommand("1"))
- fetchTextR1 = self.__iUSB.read()
- hexTextR1 = self.formatRegValPayload(fetchTextR1)
- self.__R1Entry.delete(0,99)
+ self.__R1Entry.delete(0,99) # R1 to UI.
self.__R1Entry.insert(0,hexTextR1)
-
- # read R2.
- self.__iUSB.write(self.buildReadRegisterCommand("2"))
- fetchTextR2 = self.__iUSB.read()
- hexTextR2 = self.formatRegValPayload(fetchTextR2)
- self.__R2Entry.delete(0,99)
+ self.__R2Entry.delete(0,99) # R2 to UI.
self.__R2Entry.insert(0,hexTextR2)
- # read R3.
- self.__iUSB.write(self.buildReadRegisterCommand("3"))
- fetchTextR3 = self.__iUSB.read()
- hexTextR3 = self.formatRegValPayload(fetchTextR3)
- self.__R3Entry.delete(0,99)
+ self.__R3Entry.delete(0,99) # R3 to UI.
self.__R3Entry.insert(0,hexTextR3)
-
- # read Program Counter.
- self.__iUSB.write(self.buildReadRegisterCommand("4"))
- fetchTextPC = self.__iUSB.read()
- hexTextPC = self.formatRegValPayload(fetchTextPC)
- self.__PCEntry.delete(0,99)
+ self.__PCEntry.delete(0,99) # PC to UI.
self.__PCEntry.insert(0,hexTextPC)
- # read Instruction Register high.
- self.__iUSB.write(self.buildReadRegisterCommand("5"))
- fetchTextIRH = self.__iUSB.read()
- hexTextIRH = self.formatRegValPayload(fetchTextIRH)
-
-
- # read Instruction Register low.
- self.__iUSB.write(self.buildReadRegisterCommand("6"))
- fetchTextIRL = self.__iUSB.read()
- hexTextIRL = self.formatRegValPayload(fetchTextIRL)
- hexTextIR = hexTextIRH + hexTextIRL[2:]
-
-
- self.__IREntry.delete(0,99) # 2-byte IR content to UI.
+ self.__IREntry.delete(0,99) # IR to UI.
self.__IREntry.insert(0,hexTextIR)
#----
@@ -593,6 +570,15 @@
commandText = commandText + "0000000000000"
return(commandText)
#-----------------------------------------------#-------------------------------
+ # build the command string for
+ # reading all CPU register values.
+ def buildReadAllRegisterCommand(self):
+
+ commandText = "" # build command for read register.
+ commandText = commandText + "7" # command-code.
+ commandText = commandText + "00000000000000"
+ return(commandText)
+#-----------------------------------------------#-------------------------------
# build the command-string for
# writing a value to a CPU register.
def buildWriteRegisterCommand(self,regNum,regVal):
@@ -738,3 +724,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- a/mmPython/mmUSBserial.txt Sun Sep 01 20:36:16 2013 +0000
+++ b/mmPython/mmUSBserial.txt Tue Sep 17 19:07:00 2013 +0000
@@ -17,7 +17,8 @@
openSuccess = 1
self.__serialPort = serial.Serial()
- self.__serialPort.baudrate = 9600
+ self.__serialPort.baudrate = 115200 # was 9600
+ self.__serialPort.timeout = 1 # one-second timeout.
for portIndex in range(7, -1, -1):
portString = "/dev/ttyACM" + "{}".format(portIndex)
@@ -33,19 +34,29 @@
if (openSuccess): print("successfully opened port {}.").format(portString)
else: print("could not open any port.")
+
+ self.__SER_BYTES = 18 # same as mbed program's SER_BYTES.
#-----------------------------------------------#-------------------------------
def __del__(self): # destructor.
self.__serialPort.close()
print "object destroyed."
#-----------------------------------------------#-------------------------------
+# the number of bytes written and read must both be SER_BYTES.
+# the '$' must be in bit<7> of what's written.
+
def write(self,toWrite): # write a string.
nowWrite = toWrite[:7]
- nowWrite = nowWrite + "$"
+ nowWrite = nowWrite + "$" # in <7>.
+ if (self.__SER_BYTES > 8): # flush out with 0's.
+ for loopIndex in range (0, self.__SER_BYTES - 8):
+ nowWrite = nowWrite + "0"
+# print("nowWrite {}").format(nowWrite)
self.__serialPort.write(nowWrite)
return(nowWrite)
#-----------------------------------------------#-------------------------------
def read(self): # read a string.
- gotRead = self.__serialPort.read(8)
+ gotRead = self.__serialPort.read(self.__SER_BYTES)
+# print("gotRead {}").format(gotRead)
return(gotRead)
#-----------------------------------------------#-------------------------------
#===============================================#===============================
@@ -70,3 +81,14 @@
+
+
+
+
+
+
+
+
+
+
+
--- a/mmSPI.lib Sun Sep 01 20:36:16 2013 +0000 +++ b/mmSPI.lib Tue Sep 17 19:07:00 2013 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/gatedClock/code/mmSPI/#6152c9709697 +http://mbed.org/users/gatedClock/code/mmSPI/#32cdc295f859
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/watchdog.lib Tue Sep 17 19:07:00 2013 +0000 @@ -0,0 +1,1 @@ +watchdog#f27d373a8e28
