
MSP430Andy
-
Content Count
26 -
Joined
-
Last visited
-
Days Won
1
Reputation Activity
-
MSP430Andy got a reaction from Arch_ETS in Poor Man's Command Line Shell
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:
-
MSP430Andy got a reaction from gwdeveloper in Poor Man's Command Line Shell
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:
-
MSP430Andy got a reaction from dacoffey in Poor Man's Command Line Shell
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
Edited. 1/27/12 Ti took out the terminal program in CCS v 5 but you can add it back into the software.
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
-
MSP430Andy got a reaction from V0JT4 in Poor Man's Command Line Shell
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
Edited. 1/27/12 Ti took out the terminal program in CCS v 5 but you can add it back into the software.
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
-
MSP430Andy got a reaction from bluehash in Poor Man's Command Line Shell
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
Edited. 1/27/12 Ti took out the terminal program in CCS v 5 but you can add it back into the software.
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
-
MSP430Andy got a reaction from zeke in Poor Man's Command Line Shell
Breaking news ...
The Poor Man's Command Line Shell WITH PARAMETERS is now in beta testing!
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 ...
-
MSP430Andy got a reaction from bluehash in Poor Man's Command Line Shell
Breaking news ...
The Poor Man's Command Line Shell WITH PARAMETERS is now in beta testing!
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 ...
-
MSP430Andy got a reaction from gwdeveloper in Poor Man's Command Line Shell
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.
Poor_Mans_Command_Line_Shell.zip
-
MSP430Andy got a reaction from zeke in Poor Man's Command Line Shell
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.
-
MSP430Andy got a reaction from oPossum in Poor Man's Command Line Shell
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
Edited. 1/27/12 Ti took out the terminal program in CCS v 5 but you can add it back into the software.
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
-
MSP430Andy got a reaction from gwdeveloper in Poor Man's Command Line Shell
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
Edited. 1/27/12 Ti took out the terminal program in CCS v 5 but you can add it back into the software.
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
-
MSP430Andy got a reaction from zeke in Poor Man's Command Line Shell
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
Edited. 1/27/12 Ti took out the terminal program in CCS v 5 but you can add it back into the software.
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
-
MSP430Andy reacted to oPossum in Newbee Question - How to save precious MSP430 RAM?
Declare the strings as const.
const char *foo = "string in flash";
-
MSP430Andy reacted to alvarop in G2553 Hardware UART "Hello World" Example
Anytime a packet is received, an interrupt happens and an interrupt service routine(ISR) is called. This ISR gets the packet from the CC2500. Since people want to do different things with the packets, I chose not to process packets in the ISR.
The callback function is called after a packet is received and is given the actual packet to process.
What you do is come up with your own packet processing function and tell the cc2500 library about it. That way it knows who tocall when a packet is received.
The uart_write_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.
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.
-
MSP430Andy reacted to bluehash in [ REMINDER ] Please Thank Members that help you out.
Hello everyone,
There has been alot of good questions going on in the past few weeks - accompanied with very good discussions. One way you can show your appreciation is by using the "Thanks" or "Thumbs up " button on the top right. It may be hard to notice but a screenshot always helps:
Use it if you have received something useful from a member. It takes time to write those posts and code. Consider it as karma, that's as good as it can get. :mrgreen:
Thanks everyone..and wish you a happy new year.
-
MSP430Andy got a reaction from xpg in Low cost, easy to use, RF ISM module for MSP430x
Paul, to save some time, here is the protocol for the MSPNode based on the JeeNode.
MSPNode_JeeNode_Protocol_R2.pdf
-
MSP430Andy got a reaction from oPossum in Low cost, easy to use, RF ISM module for MSP430x
Thanks, but I found a similar product by Hope RF. The RFM12B for about $6. Also, I would like to note that Hope RF is a packager of RF ICs. The RFM12B is really a Silicon Labs RF chip eg Si4420. So using the RFM70 you need to go to the "source" for the docs.
There is a person on this board eg SimpleAVR, which made a spectrum analyzer using the RFM12B, he also ported a complete, MSP430Gx library for this RFM12B using the JeeNode protocol. The JeeNode protocol/library has been around for several years of testing. It has a enum TX & RX mode states with interrupt driven RX & Tx for a 1 ua current standby for battery operation.
Github MSPNode
:thumbup:
-
MSP430Andy got a reaction from bluehash in Low cost, easy to use, RF ISM module for MSP430x
Paul goto the JeeLabs website and find the topic that has over 3800 hits. There is code examples, boards and plenty
of valuable information using the MSP430 with the RFM12B.
Hope this helps.
-
MSP430Andy got a reaction from xpg in Low cost, easy to use, RF ISM module for MSP430x
Thanks, but I found a similar product by Hope RF. The RFM12B for about $6. Also, I would like to note that Hope RF is a packager of RF ICs. The RFM12B is really a Silicon Labs RF chip eg Si4420. So using the RFM70 you need to go to the "source" for the docs.
There is a person on this board eg SimpleAVR, which made a spectrum analyzer using the RFM12B, he also ported a complete, MSP430Gx library for this RFM12B using the JeeNode protocol. The JeeNode protocol/library has been around for several years of testing. It has a enum TX & RX mode states with interrupt driven RX & Tx for a 1 ua current standby for battery operation.
Github MSPNode
:thumbup: