Jump to content
43oh

Poor Man's Command Line Shell


Recommended Posts

I needed to serially input data in my "2553" LaunchPad using the hardware Uart.

I hacked together some code which has Printf(), a receive ring buffer, Uart routines,

and the case/switch Poor Man's Command Line Shell. You need to criss-cross the tx/rx on the LP

header and use the terminal program in CCS 4.1. Please Note: CCS 5 does not have the terminal program installed ! :evil:

Note: GRACE was used to setup the USCI_A0 hw UART at 9600 8 N 1

Enjoy :D

 

Edited. 1/27/12 Ti took out the terminal program in CCS v 5 but you can add it back into the software. :D:D:D

 

http://processors.wiki.ti.com/index.php/How_to_install_the_terminal_plugin_in_CCSv5

 

/*********************************************************************************/
/*!
   THIS SOFTWARE IS PROVIDED BY THE THE 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 INSTITUTE 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.

   IF YOU USE THIS SOFTWARE AND YOUR HOUSE BURNS DOWN AND YOUR WIFE AND CHILDREN
   BECOMES HOMELESS AND WORST OF ALL YOUR DOG DIES, DON'T HOLD ME RESPONSIBLE!

   YOU CAN USE THIS CODE BUT PLEASE GIVE CREDIT TO THOSE WHO CONTRIBUTED TO IT.
   PLEASE INCLUDE ALL COPYWRITES HEADERS/FOOTERS IN YOUR SOFTWARE.
*/
/*********************************************************************************/


/*********************************************************************************/
/*!

Author: MSP430Andy
Description: LP_2553_Cmd_Line - command line shell or interpreter.
Program Revision: 1.0b (beta)
Date: 2/1/12
PC Platform: Windows PC/SP3
Development platform: LaunchPad revision 2 firmware.
PC compiler used: Eclipse with CCS 4.1 & 5 <--- Missing terminal program in 5 !!!!!
Configuration setup I/O generated by: GRACE
Device used: MSP430G2553 Pin DIP
Software Module: USCI_A0 at 9600, 8 N 1

Bugs:
1. Syntax warnings in function printf()? - routine works but there were no errors in CCS 4.1?


Code size:
2553 Device: 16K flash, 512 bytes RAM
Flash used: xxx k
RAM used: xxx bytes (without printf_Test()

Program status OK

*/
/*********************************************************************************/

/*********************************************************************************/
/*!
                                 [includes]
*/
/*********************************************************************************/

#include 

// GRACE Include
#include 

// Support Include
#include  // for printF
#include 


/*********************************************************************************/
/*!
                                 [Defines]
*/
/*********************************************************************************/

// Red LED - on board on LaunchPad
#define RED_LED_OFF()       P1OUT &= ~BIT0
#define RED_LED_ON()        P1OUT |= BIT0
#define RED_LED_FLIP()      P1OUT ^= BIT0

// Green LED - on board on LaunchPad
#define GRN_LED_OFF()       P1OUT &= ~BIT6
#define GRN_LED_ON()        P1OUT |= BIT6
#define GRN_LED_FLIP()      P1OUT ^= BIT6

#define TX_RX_DIAG 0     // [1 = Toggles LP LEDs rx = grn & tx = red]  [0 = all off]

#define SYNC_BYTE   0x7E // 127 dec
#define ESCAPE_BYTE 0x7D // 128 dec

/*********************************************************************************/
/*!
                               [Rx Ring Buffer]
*/
/*********************************************************************************/

//Ring Buffer
#define RING_BUFFER_SIZE 32
char ring_buffer[RING_BUFFER_SIZE]; // usci_A0 rx ring buffer

/* Size of RX ring buffer */
#define RING_BUFFER_MASK ( RING_BUFFER_SIZE - 1)

#if ( RING_BUFFER_SIZE & RING_BUFFER_MASK )
#error RX ring buffer size is not a power of 2
#endif

// Ring Buffer Global Variables
int ring_buffer_data_size = 0;      // number of chars in buffer
int ring_buffer_read_pointer = 0;   // indice number of last read char
int ring_buffer_write_pointer = 0;  // indice number of last written char

/*********************************************************************************/
/*!
                               [Printf]
*/
/*********************************************************************************/

//Printf Functions
void printf_putc (unsigned char c);
void printf_puts(char *s);
void printf(char *, ...);
void printf_Test(void);

/*********************************************************************************/
/*!
                           [Rx Receive Callback]
*/
/*********************************************************************************/

// Callbacks
static uint8_t dummy_callback( uint8_t ); // default ring buffer callback

// Holds pointers to all callback functions for USCI_AO rx buffer
static uint8_t (*uart_rx_callback)( uint8_t ) = dummy_callback;

/*********************************************************************************/
/*!
                           [Function Prototypes]
*/
/*********************************************************************************/

// rx ring buffer prototypes
int ring_buffer_full(void);
int ring_buffer_empty(void);
void ring_buffer_push_char(char c);          // to ring buffer
unsigned char ring_buffer_pull_char(void);   // from ring buffer <------<<<< for rx
void flush_ring_buffer(void);                // clear ring buffer with spaces 0x20

// usci_a0 uart prototypes
void uart_put_char( uint8_t );               // <-------<<<<< for tx
void uart_write_buffer( uint8_t*, uint16_t );
void uart_write_buffer_escaped( uint8_t*, uint16_t );
uint8_t hex_to_string( uint8_t* , uint8_t*, uint8_t );

// cmd line prototypes
void cmd_show_help(void);
void poll_cmd(void);



/*********************************************************************************/
/*!
                                    [Main]
*/
/*********************************************************************************/
void main(void)
{
CSL_init();            // Activate Grace-generated configuration
__enable_interrupt();  // Set global interrupt enable

flush_ring_buffer();   // clear receive ring buffer with spaces 0x20
//_________________________________________________________________________________

RED_LED_OFF();
GRN_LED_OFF();

//printf_Test();
cmd_show_help();

  while(1){
     poll_cmd();
  }
}
// end of main

/*********************************************************************************/
/*!
                               [uART_USCI_A0_RX_ISR]
*/
/*********************************************************************************/
void UART_USCI_A0_RX_ISR(void){

 // Process incoming byte from USART
  if( IFG2 & UCA0RXIFG )
  {
    // Call rx callback function (default - dummy) or
	// ring_buffer_callback if selected

    if( uart_rx_callback( UCA0RXBUF ) )
    {
      // If function returns something nonzero, wakeup the processor
      //__bic_SR_register_on_exit(LPM1_bits);
    	_nop();
    }
  }

}

/*********************************************************************************/
/*!


                         [user Application Functions]



*/
/*********************************************************************************/






/*********************************************************************************/
/*!
                               [uART Functions]
*/
/*********************************************************************************/


/*********************************************************************************/
/*!
   @fn     uart_put_char( uint8_t character )
   @brief  transmit single character
*/
/*********************************************************************************/
void uart_put_char( uint8_t character )
{
 while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
 UCA0TXBUF = character;

 if (TX_RX_DIAG){
 RED_LED_FLIP();
 }
}
/*********************************************************************************/
/*!
  @fn     uart_write_buffer( uint8_t character )
  @brief  transmit whole buffer
*/
/*********************************************************************************/
void uart_write_buffer( uint8_t* buffer, uint16_t length )
{
 uint16_t buffer_index;

 for( buffer_index = 0; buffer_index < length; buffer_index++ )
 {
   while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
   UCA0TXBUF = buffer[buffer_index];
 }
}

/*********************************************************************************/
/*!
  @fn     uart_write_buffer_escaped( uint8_t character )
  @brief  transmit whole buffer while escaping characters

 The uart_write_buffer_escaped() is more for sending whole packets through the serial
 peripheral to the computer. Normally you just send a stream of bytes. Unfortunately,
 there is no way for the computer to know when a stream of data begins or ends.
 This function uses the 0x7E byte as a start and end of packets. This way, the
 receiver knows when to begin and end capturing data.
 If your data contains a 0x7E, that might confuse the receiver, so you must escape it
 by preceding it with a 0x7D and modifying it. The receiver must be aware of this
 to process it accordingly.
*/
/*********************************************************************************/
void uart_write_buffer_escaped( uint8_t* buffer, uint16_t length )
{
 uint16_t buffer_index;

 while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
 UCA0TXBUF = SYNC_BYTE;

 for( buffer_index = 0; buffer_index < length; buffer_index++ )
 {
   if( (buffer[buffer_index] == SYNC_BYTE) | (buffer[buffer_index] == ESCAPE_BYTE) )
   {
     while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
     UCA0TXBUF = ESCAPE_BYTE;
     while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
     UCA0TXBUF = buffer[buffer_index] ^ 0x20;
   }
   else
   {

     while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
     UCA0TXBUF = buffer[buffer_index];

   }
 }

 while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
 UCA0TXBUF = SYNC_BYTE;

}

/*********************************************************************************/
/*!
  @fn     void dummy_callback( uint8_t rx_char )
  @brief  empty function works as default callback
*/
/*********************************************************************************/
static uint8_t dummy_callback( uint8_t rx_char )
{
if (TX_RX_DIAG){
  GRN_LED_FLIP();
}

//uart_put_char(rx_char); // turnaround echo to tx <----- for test only
ring_buffer_push_char(rx_char); // Put/push char into ring buffer
 return 0;
}



/*********************************************************************************/
/*!
  @fn     uint8_t hex_to_string( uint8_t* buffer_out, uint8_t* buffer_in,
                                          uint8_t buffer_in_size  )
  @brief  DEBUG function used to convert hex values to [hex]string format

  The hex_to_string function was just for debugging. When you want to display a value,
  you usually use printf(). Unfortunately, printf takes a lot of cycles to format the data,
  and if you're doing time-sensitive stuff, you can't afford the delay. In cases where
  you don't have full debugging capability, you might want to print out the values of
  some registers or variables. the hex_to_string() function converts a value to a
  hexadecimal string.
*/
/*********************************************************************************/
uint8_t hex_to_string( uint8_t* buffer_out, uint8_t* buffer_in,
                                   uint8_t buffer_in_size  )
{
 static const uint8_t hex_char[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
                                     '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
 uint8_t counter = 0;

 while( counter < buffer_in_size * 2 )
 {
   buffer_out[counter] = hex_char[((buffer_in[(counter>>1)]>>4) & 0xF)];
   counter++;
   buffer_out[counter] = hex_char[(buffer_in[(counter>>1)] & 0xF)];
   counter++;
 }

 // Terminate string with null character
 buffer_out[counter++] = 0;

 return counter;
}


/*********************************************************************************/
/*!
                             [Printf Functions]

*/
/*********************************************************************************/


/*********************************************************************************/
/*!
  @fn     void printf_putc (unsigned char c)
  @brief  put char into tx buffer
*/
/*********************************************************************************/

void printf_putc (unsigned char c)
{
_nop();
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = c;             // TX <-- c
}

/*********************************************************************************/
/*!
  @fn void printf_puts(char *s) { while(*s) printf_putc(*s++);
  @brief  put string chars into into tx buffer
*/
/*********************************************************************************/

void printf_puts(char *s) { while(*s) printf_putc(*s++); }

/*********************************************************************************/
/*!
  @fn
  @brief
*/
/*********************************************************************************/

static const unsigned long dv[] = {
//  4294967296      // 32 bit unsigned max
   1000000000,     // +0
    100000000,     // +1
     10000000,     // +2
      1000000,     // +3
       100000,     // +4
//       65535      // 16 bit unsigned max     
        10000,     // +5
         1000,     // +6
          100,     // +7
           10,     // +8
            1,     // +9
};

/*********************************************************************************/
/*!
  @fn
  @brief
*/
/*********************************************************************************/
static void xtoa(unsigned long x, const unsigned long *dp)
{
   char c;
   unsigned long d;
   if(x) {
       while(x < *dp) ++dp;
       do {
           d = *dp++;
           c = '0';
           while(x >= d) ++c, x -= d;
           printf_putc(c);
       } while(!(d & 1));
   } else
       printf_putc('0');
}
/*********************************************************************************/
/*!
  @fn
  @brief
*/
/*********************************************************************************/
static void puth(unsigned n)
{
   static const char hex[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
   printf_putc(hex[n & 15]);
}


/***********************************************************************************/
/*!
  @fn
  @brief
*/
/***********************************************************************************/

void printf(char *format, ...)
{
   char c;
   int i;
   long n;

   va_list a;
   va_start(a, format);
   while(c = *format++) {
       if(c == '%') {
           switch(c = *format++) {
               case 's':                       // String
                   printf_puts(va_arg(a, char*));
                   break;
               case 'c':                       // Char
                   printf_putc(va_arg(a, char));
                   break;
               case 'i':                       // 16 bit Integer
               case 'u':                       // 16 bit Unsigned
                   i = va_arg(a, int);
                   if(c == 'i' && i < 0) i = -i, printf_putc('-');
                   xtoa((unsigned)i, dv + 5);
                   break;
               case 'l':                       // 32 bit Long
               case 'n':                       // 32 bit uNsigned loNg
                   n = va_arg(a, long);
                   if(c == 'l' &&  n < 0) n = -n, printf_putc('-');
                   xtoa((unsigned long)n, dv);
                   break;
               case 'x':                       // 16 bit heXadecimal
                   i = va_arg(a, int);
                   puth(i >> 12);
                   puth(i >> 8);
                   puth(i >> 4);
                   puth(i);
                   break;
               case 0: return;
               default: goto bad_fmt;
           }
       } else
bad_fmt:    printf_putc(c);
   }
   va_end(a);
}

/***********************************************************************************/
/*!
  @fn
  @brief
*/
/***********************************************************************************/
void printf_Test(void){

/*
=================
Printf() for 2553
=================
There are 7 format specifiers:
%c - Character
%s - String
%i - signed Integer (16 bit)
%u - Unsigned integer (16 bit)
%l - signed Long (32 bit)
%n - uNsigned loNg (32 bit)
%x - heXadecimal (16 bit)
Field width, floating point and other standard printf() features are not supported.
*/

const char *s = "test";
const char c = 'X';
const int i = -12345;
const unsigned u = 12345;
const long int l = -1234567890;
const long unsigned n = 1234567890;
const unsigned x = 0xABCD ;  //hex



printf("%s", "\r\n*** printf() test ***\r\n");
printf("String        %s\r\n", s);
printf("Char          %c\r\n", c);
printf("Integer       %i\r\n", i);
printf("Unsigned      %u\r\n", u);
printf("Long          %l\r\n", l);
printf("uNsigned loNg %n\r\n", n);
printf("heX           %x\r\n", x);
printf("multiple args %s %c %i %u %l %n %x\r\n", s, c, i, u, l, n, x);
printf("\r\n*** Done ***\r\n");

   // printf_Test result ....

/*
*** printf() test ***
String        test
Char          X
Integer       -12345
Unsigned      12345
Long          -1234567890
uNsigned loNg 1234567890
heX           ABCD
multiple args test X -12345 12345 -1234567890 1234567890 ABCD

*** Done ***
   */
}

/*********************************************************************************/
/*!
                           [Ring Buffer Functions]
*/
/*********************************************************************************/


/*********************************************************************************/
/*!
  @fn void ring_buffer_push_char(char c)
  @brief  adds a char
*/
/*********************************************************************************/
void ring_buffer_push_char(char c)
{
   // increase ring_buffer_write_pointer, check if at end of array
   if (++ring_buffer_write_pointer >= RING_BUFFER_SIZE) ring_buffer_write_pointer = 0;

   ring_buffer[ring_buffer_write_pointer] = c;
   ring_buffer_data_size++;
}

/*********************************************************************************/
/*!
  @fn int ring_buffer_full(void)
  @brief  returns 1 if buffer is full, 0 if buffer is not full
*/
/*********************************************************************************/
int ring_buffer_full(void)
{
return ring_buffer_read_pointer == ring_buffer_write_pointer &&
 		ring_buffer_data_size == RING_BUFFER_SIZE;
}

/*********************************************************************************/
/*!
  @fn int ring_buffer_empty(void)
  @brief  returns 1 if buffer is empty, 0 if buffer is not empty
*/
/*********************************************************************************/
int ring_buffer_empty(void)
{
return ring_buffer_read_pointer == ring_buffer_write_pointer &&
		ring_buffer_data_size == 0;
}

/*********************************************************************************/
/*!
  @fn void ring_buffer_pull_char(void)
  @brief pull char from queue
*/
/*********************************************************************************/
unsigned char ring_buffer_pull_char(void)
{
 char rx; // added - also above unsigned char

 if (++ring_buffer_read_pointer >= RING_BUFFER_SIZE) ring_buffer_read_pointer = 0;

 rx = ring_buffer[ring_buffer_read_pointer];  // added

 // enter space on place of read char so we can see it is removed
 ring_buffer[ring_buffer_read_pointer] = 0x20;
 ring_buffer_data_size--;

 return rx; // added
}

/*********************************************************************************/
/*!
  @fn void flush_ring_buffer(void)
  @brief flushes ring buffer
*/
/*********************************************************************************/
void flush_ring_buffer(void){
// make sure there are no random chars in array, all spaces
int i;
for (i = 0; i < RING_BUFFER_SIZE; i++) ring_buffer[i] = 0x20; // spaces
}


/*********************************************************************************/
/*!
                          [Command Line Functions]
*/
/*********************************************************************************/


/*********************************************************************************/
/*!
  @fn void cmd_show_help(void)
  @brief show cmd line help menu
*/
/*********************************************************************************/
void cmd_show_help(void)
{
const char  *m0 = "<<--COMMAND LINE MENU-->>";
const char  *m1 = "[A] LP Red LED ON";
const char  *m2 = "[b] LP Red LED OFF";
const char  *m3 = "[C] LP Green LED ON";
const char  *m4 = "[D] LP Green LED OFF";
const char  *m5 = "[E] Command #5 Spare Text";
const char  *m6 = "[F] Command #6 Spare Text";
const char  *m7 = "[G] Command #7 Spare Text";
const char  *m8 = "[?] Show Help";
const char  *prompt = "Cmd >> ";
printf("\r\n");
printf("\r\n");
printf("%s\r\n",m0);
printf("\r\n");
printf("%s\r\n",m1);
printf("%s\r\n",m2);
printf("%s\r\n",m3);
printf("%s\r\n",m4);
printf("%s\r\n",m5);
printf("%s\r\n",m6);
printf("%s\r\n",m7);
printf("%s\r\n",m8);
printf("\r\n");
printf("%s",prompt);
}

/*********************************************************************************/
/*!
  @fn
  @brief
*/
/*********************************************************************************/

void poll_cmd(void)
{

while(1){
     char x;
     if (ring_buffer_data_size > 0){
   	x = ring_buffer_pull_char();
   	uart_put_char(x); // return/echo cmd char to uart screen
   	}
     switch (x){
        case 'A':
        case 'a':
       	 _nop();
       	 RED_LED_ON();
       	 _nop();
       	 cmd_show_help();
        break;

        case 'B':
        case 'b':
       	 _nop();
       	 RED_LED_OFF();
       	 _nop();
       	 cmd_show_help();
        break;

        case 'C':
        case 'c':
       	 GRN_LED_ON();
       	 cmd_show_help();
        break;

        case 'D':
        case 'd':
       	 GRN_LED_OFF();
       	 cmd_show_help();
        break;

        case 'E':
        case 'e':
       	 cmd_show_help();
        break;

        case 'F':
        case 'f':
       	 cmd_show_help();
        break;

        case 'G':
        case 'g':
       	 cmd_show_help();
        break;

        case '?':
            cmd_show_help();
        break;

        //default:

     } // end of case
     x = 0x20; // clear case char
     _nop();
   } // end of while
}

//=================================================================================
//=================================================================================
// The End

Link to post
Share on other sites

Why did I call this program a Poor Man's Command Line Shell? :?:

 

Using the case/switch command only allows one command (char letter) per menu selection to run

the user defined code snippet. There is also a "Rich Man's Command Line Shell" that can be

seen by the following link tutorial:

 

http://freaklabs.org/index.php/Tutorials/Software/Tutorial-Using-CmdArduino.html

 

From this tutorial, a user can type in a pre-defined function name with parameter(s) at the command prompt.

For instance, PWM 50 would tell the microcontroller to output PWM at 50%. The user function would

then parse/decode the list of parameters by the command line shell.

 

For user applications, which uses multiple parameters, like RF Node setup/configuration, this shell

would be very flexiable and useful. By inputting multiple parameters, at the command prompt, the RF node variables

could be sent to "protected flash" to be used for RF node configuration.

Also, using this "parameter command shell", networking of "2553"s would be extremely easy.

 

I tried to hack/patch this "freaklabs" command line shell on the "2553" but the complex command handlers,

parsers and tables caused total failure. Only a "professional programmer" could probably make this code functional

on the MSP430G2553. I will post my hacked code, on this board for others to fix and debug, if requested.

Link to post
Share on other sites

WARNING ... After importing the project into your workspace, do the following FIRST.

Click on the main.cfg file (GRACE) to edit and wait ... wait until all processing is done!

(see bottom right progress bar). After you can see the GRACE overview screen then rebuild the project.

This would stop any compile problems with the project files. Project compiles best with CCS v 4.1.

:D

Poor_Mans_Command_Line_Shell.zip

Link to post
Share on other sites

Oops... I forgot to include my example code snippets for reading, writing, and clearing protected

flash segment D for my RFM12B ISM RF node setup configuration parameters.

Enjoy :D

 

/*********************************************************************************/
/*!
   THIS SOFTWARE IS PROVIDED BY THE THE 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 INSTITUTE 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.

   THERE ARE BUGS IN ANY SOFTWARE. THERE COULD EVEN BE BUGS IN THIS SOFTWARE???
   IF THERE WAS A TIME TO CALL THE BUG EXTERMINATOR, NOW WOULD BE THE TIME
   TO CALL 1-800-ORKIN. COLONIES OF BUGS ARE HARD TO EXTERMINATE IF YOU
   LET THEM BREED. IF YOU CAN'T CALL ORKIN JUST FIRE UP THE CCS DEBUGGER AND
   EXTERMINATE THEM YOURSELF! 

   IF YOU USE THIS SOFTWARE AND YOUR HOUSE BURNS DOWN AND YOUR WIFE AND CHILDREN
   BECOMES HOMELESS AND WORST OF ALL YOUR DOG DIES, DON'T HOLD ME RESPONSIBLE!

   YOU CAN USE THIS CODE BUT PLEASE GIVE CREDIT TO THOSE WHO CONTRIBUTED TO IT.
   PLEASE INCLUDE ALL COPYWRITES HEADERS/FOOTERS IN YOUR SOFTWARE!
*/
/*********************************************************************************/

/*********************************************************************************/
/*!
                           [Flash Structure]

The MSP430G2553 the flash memory is organized as follow:
4 * 64 BYTE BLOCKS = 256 BYTES 
Flash_ptrA = (char *) 0x10C0; // 10C0-10FF Initialize Flash segment A pointer but never touch this! (calibration constants)
Flash_ptrB = (char *) 0x1080; // 1080-10BF Initialize Flash segment B pointer
Flash_ptrC = (char *) 0x1040; // 1040-107F Initialize Flash segment C pointer
Flash_ptrD = (char *) 0x1000; // 1000-103F Initialize Flash segment D pointer

*/
/*********************************************************************************/

// We store all the MSPNode RFM12B RF node config data in a structure so that
// we can save it in the flash memory. (MSPNode is JeeNode protocol compatible)

struct MSPNode {
// MSPNode Group ID (1-254)
unsigned char grp;
// MSPNode Node ID (1-30)
unsigned char id;
// RFM12B ISM Freq. Band <--- Marked On RFM12B chip!
  //RF12_433MHZ     1
  //RF12_868MHZ     2
  //RF12_915MHZ     3
unsigned char band;
// RFM12B Central Node ID
unsigned char dest;
} mspnode = {1,8,3,20}; // <---- init values to write to protected flash segment D (64 bytes total)

// ref. only
//mspnode.grp
//mspnode.id
//mspnode.band
//mspnode.dest


// protected flash prototypes
// *******DO NOT LOOP THE WRITE FUNCTION - WILL CAUSE FLASH WEAR FAILURES!!!!! *******

void write_P_D_Flash(void); // uses MSPNode data structure (above)
void read_P_D_Flash(void); // uses MSPNode data structure (above)
void FF_SegD (void); // put FF in all of segment D


/*********************************************************************************/
/*!

                                  PROTECTED FLASH FUNCTIONS

       WARNING ...DO NOT LOOP THE WRITE FUNCTION - WILL CAUSE FLASH WEAR FAILURES!!!!

*/
/*********************************************************************************/




/*********************************************************************************/
/*!  
 @fn write_P_D_Flash()
 @brief Writes flash structure to protected flash segment D - 2553 only
 WARNING ...DO NOT LOOP THE WRITE FUNCTION - WILL CAUSE FLASH WEAR FAILURES!!!!                                  
*/
/*********************************************************************************/
void write_P_D_Flash(void)
{
char *Flash_ptr;
char *p = (char *)&mspnode;
unsigned int i;

//WARNING ...DO NOT LOOP THE WRITE FUNCTION - WILL CAUSE FLASH WEAR FAILURES!!!!

   // uses flash MSPNode data structure (above)


Flash_ptr = (char *) 0x1000;         // was 0x103F; Flash pointer, to segment D

FCTL1 = FWKEY + ERASE;               // Set Erase bit
FCTL3 = FWKEY;                       // Clear Lock bit
*Flash_ptr = 0;                      // Dummy write to erase Flash segment

FCTL1 = FWKEY + WRT;                 // Set WRT bit for write operation
for (i=0; i	{
	*Flash_ptr++ = *p++;             // Write value to flash
}

FCTL1 = FWKEY;                       // Clear WRT bit
FCTL3 = FWKEY + LOCK;                // Set LOCK bit
}

/*********************************************************************************/
/*!  
 @fn read_P_D_Flash()
 @brief Reads flash structure to protected flash segment D - 2553 only
 WARNING ...DO NOT LOOP THE WRITE FUNCTION - WILL CAUSE FLASH WEAR FAILURES!!!!                                  
*/
/*********************************************************************************/
void read_P_D_Flash(void)
{
char *Flash_ptr;
char *p = (char *)&mspnode;
unsigned int i;

   // uses flash MSPNode data structure (above)

Flash_ptr = (char *)0x1000;   //  was 0x103F;   Flash pointer to segment D

for (i=0; i	{
	*p++ = *Flash_ptr++;
}

}

/*********************************************************************************/
/*!  
 @fn FF_SegD (void) 
 @brief Writes 0xFF to all of segment D.
 WARNING ...DO NOT LOOP THE WRITE FUNCTION - WILL CAUSE FLASH WEAR FAILURES!!!!                                  
*/
/*********************************************************************************/
void FF_SegD (void)
{
 char *Flash_ptr;                          // Flash pointer
 unsigned int i;

 Flash_ptr = (char *) 0x1000;              // Initialize Flash pointer
 FCTL1 = FWKEY + ERASE;                    // Set Erase bit
 FCTL3 = FWKEY;                            // Clear Lock bit
 *Flash_ptr = 0;                           // Dummy write to erase Flash segment

 FCTL1 = FWKEY + WRT;                      // Set WRT bit for write operation

 for (i=0; i<64; i++)
 {
   *Flash_ptr++ = 0xFF;                   // Write value to flash
 }

 FCTL1 = FWKEY;                            // Clear WRT bit
 FCTL3 = FWKEY + LOCK;                     // Set LOCK bit
}


//end

 

:D

Link to post
Share on other sites

Breaking news ...

 

The Poor Man's Command Line Shell WITH PARAMETERS is now in beta testing! :D

 

The format will be comma separated variables with the last character being the command.

 

Typing in 123,100,25,a will execute case/switch 'a' command with buf[0}, = 123, buf[1] = 100 and

buf[2] = 25. Up the 12 character parameters can be entered. (0-255)

 

Having the ability to communicate serially to the "2553" and setting up internal parameters

in protected flash will alter the operation of the microcontroller without using the development

IDE to re-program the chip. Your application code would be protected and the user would

use a serial terminal to configure the microcontroller settings.

 

Now the question arises "what can you do with it?"

 

Setting up RF nodes, networking nodes, testing devices or almost anything that needs to alter

program execution with a change in program variables or settings.

 

:ugeek: Stay tuned ...

Link to post
Share on other sites

Hardware and Software Application Notes Using the Command Line Interface:

 

The "Poor Mans Command Line" interface is a simple shell that can be run on an MSP430G2553.

It's nothing fancy and its main purpose is to allow users to easily call their functions

on a running MSP430G2553 via a simple serial terminal. It also allows users to pass in

arguments from the command line into the functions they wrote so they can easily

toggle pins, set blinking speed, set pwm duty cycles, or whatever else might need command

line user input.

 

For software, you'll need to use a serial terminal program to access the MSP430G2553 Hw serial port.

For Windows, I'd recommend using a free program like "Tera term" Pro or RealTerm .

For Linux, I'd recommend Picocom . And for Mac, you can simply use the "screen"

command built into Mac OSX. Of course, there is a terminal program, built in program, into Ti's CCS

which can be used to debug the serial data streams by the emulator electronics. The maximum

speed setup for this terminal program is 9600 8 N 1 and don't forget to cris-cross the tx/rx on the "old"

Launchpad header! This same serial communications data stream can also be viewed on the USB/VCP port,

by using a PC and any of the above terminal programs.

 

For hardware, if you are NOT using the LauchPads emulator electronics or USB/VCP port,

you'll also need to use a separate USB to TTL converter module to convert the LaunchPad's TX and RX

signals to USB.(You need to pull the header jumpers on the launchpad!)

Make sure the signals are set for 3.3 VDC operation only!!!! Sparkfun, Modern Device and Adafruit

has the USB/TTL modules.

 

BTW ... Since the PC can communicate with the LanuchPad's serial port on the "2553" via USB/VCP

then it could be very possible to have the LaunchPad connected to an Android device and have

the Android device change the I/O on the LaunchPad! That's another future project. :ugeek:

Link to post
Share on other sites

Here is my updated Command Line Interface with parameters. (Beta)

:ugeek:

 

/*********************************************************************************/
/*!
   THIS SOFTWARE IS PROVIDED BY THE THE 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 INSTITUTE 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.

   THERE ARE BUGS IN ANY SOFTWARE. THERE COULD EVEN BE BUGS IN THIS SOFTWARE???
   IF THERE WAS A TIME TO CALL THE BUG EXTERMINATOR, NOW WOULD BE THE TIME
   TO CALL 1-800-ORKIN. COLONIES OF BUGS ARE HARD TO EXTERMINATE IF YOU
   LET THEM BREED. IF YOU CAN'T CALL ORKIN JUST FIRE UP THE CCS DEBUGGER AND
   EXTERMINATE THEM YOURSELF! 

   IF YOU USE THIS SOFTWARE AND YOUR HOUSE BURNS DOWN AND YOUR WIFE AND CHILDREN
   BECOMES HOMELESS AND WORST OF ALL YOUR DOG DIES, DON'T HOLD ME RESPONSIBLE!

   YOU CAN USE THIS CODE BUT PLEASE GIVE CREDIT TO THOSE WHO CONTRIBUTED TO IT.
   PLEASE INCLUDE ALL COPYWRITES HEADERS/FOOTERS IN YOUR SOFTWARE!
*/
/*********************************************************************************/


/*********************************************************************************/
/*!

Author: MSP430Andy
Description: LP_2553_Cmd_Line - command line interface or shell or interpreter.
Program Revision: 1.0b (beta)
Date: 1/30/12
PC Platform: Windows PC/SP3
Development platform: LaunchPad revision 2 firmware.
PC compiler used: Eclipse with CCS 4.1 & 5 
Configuration setup I/O generated by: GRACE
Device used: MSP430G2553 Pin DIP
Software Module: USCI_A0 at 9600, 8 N 1

Bugs:
1. Syntax warnings in function printf()? - routine works but there were no errors in CCS 4.1?


Code size:
2553 Device: 16K flash, 512 bytes RAM
Flash used: xxx k
RAM used: xxx bytes (without printf_Test()

Program status OK

*/
/*********************************************************************************/

/*********************************************************************************/
/*!
                                 [includes]
*/
/*********************************************************************************/

#include 

// GRACE Include
#include 

// Support Include
#include  // for printF
#include 


/*********************************************************************************/
/*!
                                 [Defines]
*/
/*********************************************************************************/

#ifdef MSP430
static void __inline__ __delay_cycles(register uint16_t n) {
// 2553 @ 1 Mhz = 1 usec  __delay_cycles(1000); = 1 msec    
   __asm__ __volatile__ (
               "1: \n"
               " dec      %[n] \n"
               " jne      1b \n"
       : [n] "+r"(n));

}
#else
#endif



// Red LED - on board on LaunchPad
#define RED_LED_OFF()       P1OUT &= ~BIT0
#define RED_LED_ON()        P1OUT |= BIT0
#define RED_LED_FLIP()      P1OUT ^= BIT0

// Green LED - on board on LaunchPad
#define GRN_LED_OFF()       P1OUT &= ~BIT6
#define GRN_LED_ON()        P1OUT |= BIT6
#define GRN_LED_FLIP()      P1OUT ^= BIT6

#define TX_RX_DIAG 0     // [1 = Toggles LP LEDs rx = grn & tx = red]  [0 = all off] - careful for testing only

#define SYNC_BYTE   0x7E // 127 dec
#define ESCAPE_BYTE 0x7D // 128 dec

// Command Line Interface
#define PARSE_BUFFER_MAX 16
#define COMMAND_LINE_STYLE  1     // <---<<<< 0 = CLI NO PARAMETERS  1 = CLI with PARAMETERS
static char value;
static char stack[PARSE_BUFFER_MAX];
static char top;



/*********************************************************************************/
/*!
                               [Rx Ring Buffer]
*/
/*********************************************************************************/

//Ring Buffer
#define RING_BUFFER_SIZE 32
char ring_buffer[RING_BUFFER_SIZE]; // usci_A0 rx ring buffer

/* Size of RX ring buffer */
#define RING_BUFFER_MASK ( RING_BUFFER_SIZE - 1)

#if ( RING_BUFFER_SIZE & RING_BUFFER_MASK )
#error RX ring buffer size is not a power of 2
#endif

// Ring Buffer Global Variables
int ring_buffer_data_size     = 0;      // number of chars in buffer
int ring_buffer_read_pointer  = 0;   // indice number of last read char
int ring_buffer_write_pointer = 0;  // indice number of last written char

/*********************************************************************************/
/*!
                               [Printf]
*/
/*********************************************************************************/

//Printf Functions
void printf_putc (unsigned char c);
void printf_puts(char *s);
void printf(char *, ...);
void printf_Test(void);

/*********************************************************************************/
/*!
                           [Rx Receive Callback]
*/
/*********************************************************************************/

// Callbacks
static uint8_t dummy_callback( uint8_t ); // default ring buffer callback

// Holds pointers to all callback functions for USCI_AO rx buffer
static uint8_t (*uart_rx_callback)( uint8_t ) = dummy_callback;

/*********************************************************************************/
/*!
                           [Flash Structure]

The MSP430G2553 the flash memory is organized as follow:
4 * 64 BYTE BLOCKS = 256 BYTES 
Flash_ptrA = (char *) 0x10C0; // 10C0-10FF Initialize Flash segment A pointer but never touch this! (calibration constants)
Flash_ptrB = (char *) 0x1080; // 1080-10BF Initialize Flash segment B pointer
Flash_ptrC = (char *) 0x1040; // 1040-107F Initialize Flash segment C pointer
Flash_ptrD = (char *) 0x1000; // 1000-103F Initialize Flash segment D pointer

*/
/*********************************************************************************/

// We store all the MSPNode RFM12B RF node config data in a structure so that
// we can save it in the flash memory. (MSPNode is JeeNode protocol compatible)

struct MSPNode {
// MSPNode Group ID (1-254)
unsigned char grp;
// MSPNode Node ID (1-30)
unsigned char id;
// RFM12B ISM Freq. Band <--- Marked On RFM12B chip!
  //RF12_433MHZ     1
  //RF12_868MHZ     2
  //RF12_915MHZ     3
unsigned char band;
// RFM12B Central Node ID
unsigned char dest;
} mspnode = {1,8,3,20}; // <---- init values to write to protected flash segment D (64 bytes total)

// ref. only
//mspnode.grp
//mspnode.id
//mspnode.band
//mspnode.dest

/*********************************************************************************/
/*!
                           [Function Prototypes]
*/
/*********************************************************************************/

// rx ring buffer prototypes
int ring_buffer_full(void);
int ring_buffer_empty(void);
void ring_buffer_push_char(char c);          // to ring buffer
unsigned char ring_buffer_pull_char(void);   // from ring buffer <------<<<< for rx
void flush_ring_buffer(void);                // clear ring buffer with spaces 0x20

// usci_a0 uart prototypes
void uart_put_char( uint8_t );               // <-------<<<<< for tx
void uart_write_buffer( uint8_t*, uint16_t );
void uart_write_buffer_escaped( uint8_t*, uint16_t );
uint8_t hex_to_string( uint8_t* , uint8_t*, uint8_t );

// cmd line with parameters prototypes
void cmd_show_help(void);
void poll_cmd(void);

// cmd line with parameters prototypes
void poll_cmd_1(void);
void cmd_show_help_1(void);

static void parse_Input(char c);

// protected flash prototypes
// *******DO NOT LOOP THE WRITE FUNCTION - WILL CAUSE FLASH WEAR FAILURES!!!!! *******

void write_P_D_Flash(void); // uses MSPNode data structure (above)
void read_P_D_Flash(void);  // uses MSPNode data structure (above)
void FF_SegD (void);        // put FF in all of segment D


/*********************************************************************************/
/*!
                                    [Main]
*/
/*********************************************************************************/
void main(void)
{
CSL_init();            // Activate Grace-generated configuration
__enable_interrupt();  // Set global interrupt enable

flush_ring_buffer();   // clear receive ring buffer with spaces 0x20
//_________________________________________________________________________________

RED_LED_OFF();
GRN_LED_OFF();

if (COMMAND_LINE_STYLE == 0){
{
}
cmd_show_help(); // CLI test no parameters
}
else
{
cmd_show_help_1(); // CLI test with parameters
printf("Cmd >> ");
}

  while(1){
   if (COMMAND_LINE_STYLE == 0){
   poll_cmd();   // CLI test no parameters
   }
   else
   {
   poll_cmd_1(); // CLI test with parameters
   }
  }
}
// end of main

/*********************************************************************************/
/*!
                               [uART_USCI_A0_RX_ISR]
*/
/*********************************************************************************/
void UART_USCI_A0_RX_ISR(void){

 // Process incoming byte from USART
  if( IFG2 & UCA0RXIFG )
  {
    // Call rx callback function (default - dummy) or
	// ring_buffer_callback if selected

    if( uart_rx_callback( UCA0RXBUF ) )
    {
      // If function returns something nonzero, wakeup the processor
      //__bic_SR_register_on_exit(LPM1_bits);
    	_nop();
    }
  }

}

/*********************************************************************************/
/*!


                         [user Application Functions]



*/
/*********************************************************************************/






/*********************************************************************************/
/*!
                               [uART Functions]
*/
/*********************************************************************************/


/*********************************************************************************/
/*!
   @fn     uart_put_char( uint8_t character )
   @brief  transmit single character
*/
/*********************************************************************************/
void uart_put_char( uint8_t character )
{
 while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
 UCA0TXBUF = character;

 if (TX_RX_DIAG){
 RED_LED_FLIP();
 }
}
/*********************************************************************************/
/*!
  @fn     uart_write_buffer( uint8_t character )
  @brief  transmit whole buffer
*/
/*********************************************************************************/
void uart_write_buffer( uint8_t* buffer, uint16_t length )
{
 uint16_t buffer_index;

 for( buffer_index = 0; buffer_index < length; buffer_index++ )
 {
   while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
   UCA0TXBUF = buffer[buffer_index];
 }
}

/*********************************************************************************/
/*!
  @fn     uart_write_buffer_escaped( uint8_t character )
  @brief  transmit whole buffer while escaping characters

 The uart_write_buffer_escaped() is more for sending whole packets through the serial
 peripheral to the computer. Normally you just send a stream of bytes. Unfortunately,
 there is no way for the computer to know when a stream of data begins or ends.
 This function uses the 0x7E byte as a start and end of packets. This way, the
 receiver knows when to begin and end capturing data.
 If your data contains a 0x7E, that might confuse the receiver, so you must escape it
 by preceding it with a 0x7D and modifying it. The receiver must be aware of this
 to process it accordingly.
*/
/*********************************************************************************/
void uart_write_buffer_escaped( uint8_t* buffer, uint16_t length )
{
 uint16_t buffer_index;

 while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
 UCA0TXBUF = SYNC_BYTE;

 for( buffer_index = 0; buffer_index < length; buffer_index++ )
 {
   if( (buffer[buffer_index] == SYNC_BYTE) | (buffer[buffer_index] == ESCAPE_BYTE) )
   {
     while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
     UCA0TXBUF = ESCAPE_BYTE;
     while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
     UCA0TXBUF = buffer[buffer_index] ^ 0x20;
   }
   else
   {

     while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
     UCA0TXBUF = buffer[buffer_index];

   }
 }

 while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
 UCA0TXBUF = SYNC_BYTE;

}

/*********************************************************************************/
/*!
  @fn     void dummy_callback( uint8_t rx_char )
  @brief  empty function works as default callback
*/
/*********************************************************************************/
static uint8_t dummy_callback( uint8_t rx_char )
{
if (TX_RX_DIAG){
  GRN_LED_FLIP();
}

//uart_put_char(rx_char); // turnaround echo to tx <----- for test only
ring_buffer_push_char(rx_char); // Put/push char into ring buffer
 return 0;
}

/*********************************************************************************/
/*!
  @fn     uint8_t hex_to_string( uint8_t* buffer_out, uint8_t* buffer_in,
                                          uint8_t buffer_in_size  )
  @brief  DEBUG function used to convert hex values to [hex]string format

  The hex_to_string function was just for debugging. When you want to display a value,
  you usually use printf(). Unfortunately, printf takes a lot of cycles to format the data,
  and if you're doing time-sensitive stuff, you can't afford the delay. In cases where
  you don't have full debugging capability, you might want to print out the values of
  some registers or variables. the hex_to_string() function converts a value to a
  hexadecimal string.
*/
/*********************************************************************************/
uint8_t hex_to_string( uint8_t* buffer_out, uint8_t* buffer_in,
                                   uint8_t buffer_in_size  )
{
 static const uint8_t hex_char[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
                                     '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
 uint8_t counter = 0;

 while( counter < buffer_in_size * 2 )
 {
   buffer_out[counter] = hex_char[((buffer_in[(counter>>1)]>>4) & 0xF)];
   counter++;
   buffer_out[counter] = hex_char[(buffer_in[(counter>>1)] & 0xF)];
   counter++;
 }

 // Terminate string with null character
 buffer_out[counter++] = 0;

 return counter;
}


/*********************************************************************************/
/*!
                             [Printf Functions]

*/
/*********************************************************************************/


/*********************************************************************************/
/*!
  @fn     void printf_putc (unsigned char c)
  @brief  put char into tx buffer
*/
/*********************************************************************************/

void printf_putc (unsigned char c)
{
_nop();
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = c;             // TX <-- c
}

/*********************************************************************************/
/*!
  @fn void printf_puts(char *s) { while(*s) printf_putc(*s++);
  @brief  put string chars into into tx buffer
*/
/*********************************************************************************/

void printf_puts(char *s) { while(*s) printf_putc(*s++); }

/*********************************************************************************/
/*!
  @fn
  @brief
*/
/*********************************************************************************/

static const unsigned long dv[] = {
//  4294967296      // 32 bit unsigned max
   1000000000,     // +0
    100000000,     // +1
     10000000,     // +2
      1000000,     // +3
       100000,     // +4
//       65535      // 16 bit unsigned max     
        10000,     // +5
         1000,     // +6
          100,     // +7
           10,     // +8
            1,     // +9
};

/*********************************************************************************/
/*!
  @fn
  @brief
*/
/*********************************************************************************/
static void xtoa(unsigned long x, const unsigned long *dp)
{
   char c;
   unsigned long d;
   if(x) {
       while(x < *dp) ++dp;
       do {
           d = *dp++;
           c = '0';
           while(x >= d) ++c, x -= d;
           printf_putc(c);
       } while(!(d & 1));
   } else
       printf_putc('0');
}
/*********************************************************************************/
/*!
  @fn
  @brief
*/
/*********************************************************************************/
static void puth(unsigned n)
{
   static const char hex[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
   printf_putc(hex[n & 15]);
}


/***********************************************************************************/
/*!
  @fn
  @brief
*/
/***********************************************************************************/

void printf(char *format, ...)
{
   char c;
   int i;
   long n;

   va_list a;
   va_start(a, format);
   while(c = *format++) {
       if(c == '%') {
           switch(c = *format++) {
               case 's':                       // String
                   printf_puts(va_arg(a, char*));
                   break;
               case 'c':                       // Char
                   printf_putc(va_arg(a, char));
                   break;
               case 'i':                       // 16 bit Integer
               case 'u':                       // 16 bit Unsigned
                   i = va_arg(a, int);
                   if(c == 'i' && i < 0) i = -i, printf_putc('-');
                   xtoa((unsigned)i, dv + 5);
                   break;
               case 'l':                       // 32 bit Long
               case 'n':                       // 32 bit uNsigned loNg
                   n = va_arg(a, long);
                   if(c == 'l' &&  n < 0) n = -n, printf_putc('-');
                   xtoa((unsigned long)n, dv);
                   break;
               case 'x':                       // 16 bit heXadecimal
                   i = va_arg(a, int);
                   puth(i >> 12);
                   puth(i >> 8);
                   puth(i >> 4);
                   puth(i);
                   break;
               case 0: return;
               default: goto bad_fmt;
           }
       } else
bad_fmt:    printf_putc(c);
   }
   va_end(a);
}

/***********************************************************************************/
/*!
  @fn
  @brief
*/
/***********************************************************************************/
void printf_Test(void){

/*
=================
Printf() for 2553
=================
There are 7 format specifiers:
%c - Character
%s - String
%i - signed Integer (16 bit)
%u - Unsigned integer (16 bit)
%l - signed Long (32 bit)
%n - uNsigned loNg (32 bit)
%x - heXadecimal (16 bit)
Field width, floating point and other standard printf() features are not supported.
*/

const char *s = "test";
const char c = 'X';
const int i = -12345;
const unsigned u = 12345;
const long int l = -1234567890;
const long unsigned n = 1234567890;
const unsigned x = 0xABCD ;  //hex



printf("%s", "\r\n*** printf() test ***\r\n");
printf("String        %s\r\n", s);
printf("Char          %c\r\n", c);
printf("Integer       %i\r\n", i);
printf("Unsigned      %u\r\n", u);
printf("Long          %l\r\n", l);
printf("uNsigned loNg %n\r\n", n);
printf("heX           %x\r\n", x);
printf("multiple args %s %c %i %u %l %n %x\r\n", s, c, i, u, l, n, x);
printf("\r\n*** Done ***\r\n");

   // printf_Test result ....

/*
*** printf() test ***
String        test
Char          X
Integer       -12345
Unsigned      12345
Long          -1234567890
uNsigned loNg 1234567890
heX           ABCD
multiple args test X -12345 12345 -1234567890 1234567890 ABCD

*** Done ***
   */
}

/*********************************************************************************/
/*!
                           [Ring Buffer Functions]
*/
/*********************************************************************************/


/*********************************************************************************/
/*!
  @fn void ring_buffer_push_char(char c)
  @brief  adds a char
*/
/*********************************************************************************/
void ring_buffer_push_char(char c)
{
   // increase ring_buffer_write_pointer, check if at end of array
   if (++ring_buffer_write_pointer >= RING_BUFFER_SIZE) ring_buffer_write_pointer = 0;

   ring_buffer[ring_buffer_write_pointer] = c;
   ring_buffer_data_size++;
}

/*********************************************************************************/
/*!
  @fn int ring_buffer_full(void)
  @brief  returns 1 if buffer is full, 0 if buffer is not full
*/
/*********************************************************************************/
int ring_buffer_full(void)
{
return ring_buffer_read_pointer == ring_buffer_write_pointer &&
 		ring_buffer_data_size == RING_BUFFER_SIZE;
}

/*********************************************************************************/
/*!
  @fn int ring_buffer_empty(void)
  @brief  returns 1 if buffer is empty, 0 if buffer is not empty
*/
/*********************************************************************************/
int ring_buffer_empty(void)
{
return ring_buffer_read_pointer == ring_buffer_write_pointer &&
		ring_buffer_data_size == 0;
}

/*********************************************************************************/
/*!
  @fn void ring_buffer_pull_char(void)
  @brief pull char from queue
*/
/*********************************************************************************/
unsigned char ring_buffer_pull_char(void)
{
 char rx; // added - also above unsigned char

 if (++ring_buffer_read_pointer >= RING_BUFFER_SIZE) ring_buffer_read_pointer = 0;

 rx = ring_buffer[ring_buffer_read_pointer];  // added

 // enter space on place of read char so we can see it is removed
 ring_buffer[ring_buffer_read_pointer] = 0x20;
 ring_buffer_data_size--;

 return rx; // added
}

/*********************************************************************************/
/*!
  @fn void flush_ring_buffer(void)
  @brief flushes ring buffer
*/
/*********************************************************************************/
void flush_ring_buffer(void){
// make sure there are no random chars in array, all spaces
int i;
for (i = 0; i < RING_BUFFER_SIZE; i++) ring_buffer[i] = 0x20; // spaces
}


/*********************************************************************************/
/*!
                          [Command Line Functions]
*/
/*********************************************************************************/


/*********************************************************************************/
/*!
  @fn void cmd_show_help(void)
  @brief show cmd line help menu
*/
/*********************************************************************************/
void cmd_show_help(void)
{
const char  *m0 = "<<--COMMAND LINE MENU-->>";
const char  *m1 = "[A] LP Red LED ON";
const char  *m2 = "[b] LP Red LED OFF";
const char  *m3 = "[C] LP Green LED ON";
const char  *m4 = "[D] LP Green LED OFF";
const char  *m5 = "[E] Wr Data --> Prot. Flash Seg. D ";
const char  *m6 = "[F] Rd Data <-- Prot. Flash Seg. D ";
const char  *m7 = "[G] Wr / CLR Prot. Flash Seg. D with 0xFF";
const char  *m8 = "[H] Show Help";
const char  *prompt = "Cmd >> ";
printf("\r\n");
printf("\r\n");
printf("%s\r\n",m0);
printf("\r\n");
printf("%s\r\n",m1);
printf("%s\r\n",m2);
printf("%s\r\n",m3);
printf("%s\r\n",m4);
printf("%s\r\n",m5);
printf("%s\r\n",m6);
printf("%s\r\n",m7);
printf("%s\r\n",m8);
printf("\r\n");
printf("%s",prompt);
}

/*********************************************************************************/
/*!
  @fn void cmd_show_help_1(void)
  @brief show cmd line help menu
*/
/*********************************************************************************/
void cmd_show_help_1(void)
{
const char  *m0 = "<<--COMMAND LINE MENU-->>";
const char  *m1 = "[A] LP Red LED ON";
const char  *m2 = "[b] LP Red LED OFF";
const char  *m3 = "[C] Toggle Red & Grn LEDs";
const char  *m4 = "[C] P1=1 Red LED ON";
const char  *m5 = "[C] P2=2 Grn LED ON";
const char  *m6 = "[C] P2=3 Red & Grn LEDs OFF";
const char  *m7 = "[H] Show Help";

printf("\r\n");
printf("\r\n");
printf("%s\r\n",m0);
printf("\r\n");
printf("%s\r\n",m1);
printf("%s\r\n",m2);
printf("%s\r\n",m3);
printf("%s\r\n",m4);
printf("%s\r\n",m5);
printf("%s\r\n",m6);
printf("%s\r\n",m7);
}

/*********************************************************************************/
/*!
  @fn poll_cmd(void)
  @brief Polls case/switch for keypress 
*/
/*********************************************************************************/

void poll_cmd(void)
{
const char  *FW = "   Wr --> prot. flash seg. D ...";
const char  *FR = "   Rd <-- prot. flash seg. D ...";
const char  *FC = "   Wr --> prot. flash seg. D with 0xFF ...";

while(1){
     char x;
     if (ring_buffer_data_size > 0){
   	x = ring_buffer_pull_char();
   	uart_put_char(x); // return/echo cmd char to uart screen
   	}
     switch (x){
        case 'A':
        case 'a':
       	 _nop();
       	 RED_LED_ON();
       	 _nop();
       	 cmd_show_help();
        break;

        case 'B':
        case 'b':
       	 _nop();
       	 RED_LED_OFF();
       	 _nop();
       	 cmd_show_help();
        break;

        case 'C':
        case 'c':
       	 GRN_LED_ON();
       	 cmd_show_help();
        break;

        case 'D':
        case 'd':
       	 GRN_LED_OFF();
       	 cmd_show_help();
        break;

        case 'E':
        case 'e':
            //MSPNode structure ref. only
            // write flash with MSPNode data
            mspnode.grp   = 1;
            mspnode.id    = 8;
            mspnode.band  = 3;
            mspnode.dest  = 20;

            write_P_D_Flash(); // uses flash MSPNode data structure (above)
            printf("%s\r\n", FW );
       	 cmd_show_help();
        break;

        case 'F':
        case 'f':
            read_P_D_Flash(); // uses flash MSPNode data structure (above)

            //MSPNode structure ref. only
            //mspnode.grp
            //mspnode.id
            //mspnode.band
            //mspnode.dest

            printf("%s\r\n", FR);     
            printf(" Group ID = %x\r\n", mspnode.grp);
            printf(" Node ID  = %x\r\n", mspnode.id);
            printf(" Band     = %x\r\n", mspnode.band);
            printf(" Dest ID  = %x\r\n", mspnode.dest);
            printf(" 10 Second Delay ... Please wait ... \r\n");
            __delay_cycles(10000000); // 10 secs
       	 cmd_show_help();
        break;

        case 'G':
        case 'g':                          
            FF_SegD (); // write 0xFF in all of seg D
            printf("%s\r\n", FC );
       	 cmd_show_help();
        break;


        case 'H':
        case 'h':
        cmd_show_help();
        break;

        //default:

     } // end of case
     x = 0x20; // clear case char
     _nop();
   } // end of while
}

/*********************************************************************************/
/*!
  @fn parse_Input(char c)
  @brief parses the user input char(s) and executes the case/switch command
  Cmd Format: p1,p2,p3,...cCR  p1,p2,p3 = 0-255 Max, c is the cmd,  chars 'a/A' - 'z/Z' & CR = enter/carriage return
  Examples: Cmd >> cCR --> will toggle both LEDs (stack[0]) with no other commands
            Cmd >> 1,0,0,cCR --> will turn on the red LED            (stack[0])
            Cmd >> 0,2,0,cCR --> will turn on the green LED          (stack[1])
            Cmd >> 0,0,3,cCR --> will turn off both red / green LEDs (stack[2])
*/
/*********************************************************************************/
static void parse_Input(char c){
const char *status0 = "Toggle Red & Green LEDs ";
const char *status1 = "Red LED ON ";
const char *status2 = "Green LED ON ";
const char *status3 = "Red & Green LEDs OFF ";
char cr = NULL;

uart_put_char(c); // return/echo char to uart screen
if ('0' <= c && c <= '9')
        value = 10 * value + c - '0';
    else if (c == ',') {
        if (top < sizeof stack)
            stack[top++] = value;
        value = 0;
    _nop();
    } else if (('a' <= c && c <='z') || ('A' <= c && c <='Z')) {
    	stack[top++] = c; // store command on stack
    	while (!(cr == 0x0D)){  // wait for CR 0x0D
    		if (ring_buffer_data_size > 0)   // data available
    			cr = ring_buffer_pull_char();
    		__delay_cycles(1000); // 1 ms
    	}
    	stack[top++] = cr; // store CR on stack
    	stack[top--] = c;  // get and process command from stack

        switch (c) {
                   default:
                   printf(" Cmd >> ");
        	       break;

                   case 'A':
                   case 'a':
                   _nop();
                   RED_LED_ON();
                   printf( "\r\nRed LED ON\r\n");
                   _nop();
                   break;

                   case 'B':
                   case 'b':
                   _nop();
                   RED_LED_OFF();
                   printf( "\r\nRed LED OFF\r\n");
                   break;

                   case 'C':  // command line parameter test
                   case 'c':
                   _nop();
                   // Process command only
                   _nop();
                   if ((stack[0] == 'c') || (stack[0] == 'C')){ // stack buffer begins stack[0]
                	   // toggle both red and green LEDs
                	  	RED_LED_FLIP();
                	  	GRN_LED_FLIP();
                	  	printf("\r\n%s\r\n",status0);
                	    break; // No parameters were entered - just the command was entered
                        }
                       // Process parameters
                       // Parameter input values of 0-255
                       _nop();
                       if (stack[0] == 0x01){ // first parameter
                    	   // Turn Red LED ON
                    	   RED_LED_ON();
                    	   _nop();
                    	   printf("%\r\n%s\r\n",status1);
                           _nop();
                       }
                       if (stack[1] == 0x02){ // second parameter
                    	   // Turn Green LED ON
                    	   GRN_LED_ON();
                    	   _nop();
                    	   printf("%\r\n%s\r\n",status2);
                    	   _nop();
                       }
                       if (stack[2] == 0x03){ // third parameter
                    	   // Turn both LEDs off
                    	   RED_LED_OFF();
                           GRN_LED_OFF();
                           printf("\r\n%s\r\n",status3);
                           _nop();
                       }
                   break;

                   case 'H':
                   case 'h':
                   _nop();
                   cmd_show_help_1();
                   //status = "Show Help";
                   break;

        } // end of case
        _nop();
       	printf("\r\nCmd >> ");
        value = top = 0;
        memset(stack, 0, sizeof stack);
    } else if (c > ' '){ // greater than 'space'
    	value = top = 0;
    }

       if (c == 0x0D){ // exit on CR
    	value = top = 0;
    	memset(stack, 0, sizeof stack);
    	printf("\r\nCmd >> ");
    }

} // eof

/*********************************************************************************/
/*!
  @fn poll_cmd_1(void)
  @brief
*/
/*********************************************************************************/

void poll_cmd_1(void)
{
    if (ring_buffer_data_size > 0)   // data available
        parse_Input(ring_buffer_pull_char());
}

/*********************************************************************************/
/*!

                                  PROTECTED FLASH FUNCTIONS

       WARNING ...DO NOT LOOP THE WRITE FUNCTION - WILL CAUSE FLASH WEAR FAILURES!!!!

*/
/*********************************************************************************/




/*********************************************************************************/
/*!  
 @fn write_P_D_Flash()
 @brief Writes flash structure to protected flash segment D - 2553 only
 WARNING ...DO NOT LOOP THE WRITE FUNCTION - WILL CAUSE FLASH WEAR FAILURES!!!!                                  
*/
/*********************************************************************************/
void write_P_D_Flash(void)
{
char *Flash_ptr;
char *p = (char *)&mspnode;
unsigned int i;

//WARNING ...DO NOT LOOP THE WRITE FUNCTION - WILL CAUSE FLASH WEAR FAILURES!!!!

   // uses flash MSPNode data structure (above)


Flash_ptr = (char *) 0x1000;         // was 0x103F; Flash pointer, to segment D

FCTL1 = FWKEY + ERASE;               // Set Erase bit
FCTL3 = FWKEY;                       // Clear Lock bit
*Flash_ptr = 0;                      // Dummy write to erase Flash segment

FCTL1 = FWKEY + WRT;                 // Set WRT bit for write operation
for (i=0; i	{
	*Flash_ptr++ = *p++;             // Write value to flash
}

FCTL1 = FWKEY;                       // Clear WRT bit
FCTL3 = FWKEY + LOCK;                // Set LOCK bit
}

/*********************************************************************************/
/*!  
 @fn read_P_D_Flash()
 @brief Reads flash structure to protected flash segment D - 2553 only
 WARNING ...DO NOT LOOP THE WRITE FUNCTION - WILL CAUSE FLASH WEAR FAILURES!!!!                                  
*/
/*********************************************************************************/
void read_P_D_Flash(void)
{
char *Flash_ptr;
char *p = (char *)&mspnode;
unsigned int i;

   // uses flash MSPNode data structure (above)

Flash_ptr = (char *)0x1000;   //  was 0x103F;   Flash pointer to segment D

for (i=0; i	{
	*p++ = *Flash_ptr++;
}

}

/*********************************************************************************/
/*!  
 @fn FF_SegD (void) 
 @brief Writes 0xFF to all of segment D.
 WARNING ...DO NOT LOOP THE WRITE FUNCTION - WILL CAUSE FLASH WEAR FAILURES!!!!                                  
*/
/*********************************************************************************/
void FF_SegD (void)
{
 char *Flash_ptr;                          // Flash pointer
 unsigned int i;

 Flash_ptr = (char *) 0x1000;              // Initialize Flash pointer
 FCTL1 = FWKEY + ERASE;                    // Set Erase bit
 FCTL3 = FWKEY;                            // Clear Lock bit
 *Flash_ptr = 0;                           // Dummy write to erase Flash segment

 FCTL1 = FWKEY + WRT;                      // Set WRT bit for write operation

 for (i=0; i<64; i++)
 {
   *Flash_ptr++ = 0xFF;                   // Write value to flash
 }

 FCTL1 = FWKEY;                            // Clear WRT bit
 FCTL3 = FWKEY + LOCK;                     // Set LOCK bit
}

//=================================================================================
//=================================================================================
// The End

 

 

LP_2553_Cmd_Line_Test_R6.zip (Beta)

:ugeek:

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...