| /* |
| * ======== SysUart.c ======== |
| */ |
| #include <xdc/runtime/Startup.h> |
| |
| #include "package/internal/SysUart.xdc.h" |
| |
| #define USE_8MHZ 1 |
| |
| #define RED 0x01 |
| #define GREEN 0x02 |
| |
| #define FOREVER -1 |
| |
| static void etx(); |
| static void flash(Int color, Int period, Int count); |
| static void init(void); |
| static void myPutc(Char ch); |
| |
| /* |
| * ======== SysUart_Module_startup ======== |
| */ |
| Int SysUart_Module_startup(Int state) |
| { |
| init(); |
| return (Startup_DONE); |
| } |
| |
| /* |
| * ======== SysUart_abort ======== |
| */ |
| Void SysUart_abort(String str) |
| { |
| if (str != NULL) { |
| Char ch; |
| |
| while ((ch = *str++) != '\0') { |
| SysUart_putch(ch); |
| } |
| } |
| flash(RED, FOREVER, FOREVER); |
| etx(); |
| } |
| |
| /* |
| * ======== SysUart_exit ======== |
| */ |
| Void SysUart_exit(Int stat) |
| { |
| flash(GREEN, FOREVER, FOREVER); |
| etx(); |
| } |
| |
| /* |
| * ======== SysUart_flush ======== |
| */ |
| Void SysUart_flush() |
| { |
| } |
| |
| /* |
| * ======== SysUart_putch ======== |
| */ |
| Void SysUart_putch(Char ch) |
| { |
| myPutc(ch); |
| } |
| |
| /* |
| * ======== SysUart_ready ======== |
| */ |
| Bool SysUart_ready() |
| { |
| return (TRUE); |
| } |
| |
| /* |
| * ======== atexit ======== |
| * The TI RTS library's atexit() implementation requires a _huge_ amount of |
| * data. We stub it out here and replace exit() and abort() with functions |
| * that are sufficient for the proper operation of xdc.runtime.System. |
| */ |
| int atexit(void (*fxn)(void)) |
| { |
| return (0); |
| } |
| |
| /* |
| * ======== abort ======== |
| * See atexit() above |
| */ |
| void abort(void) |
| { |
| /* Define C$$EXIT label because TI debugger uses this to know when |
| * programs terminate. This can be removed if the debugger is not |
| * used. |
| */ |
| __asm(" .global C$$EXIT"); |
| __asm("C$$EXIT: nop"); |
| |
| for (;;); /* spin forever */ |
| } |
| |
| /* |
| * ======== exit ======== |
| * See atexit() above |
| */ |
| void exit(int status) |
| { |
| SysUart_exit(status); |
| } |
| |
| /* |
| * ======== etx ======== |
| * Flush HW TX buffers |
| */ |
| static void etx() |
| { |
| myPutc(4); /* ascii EOT */ |
| myPutc(0); |
| myPutc(0); |
| abort(); |
| } |
| |
| #if 0 |
| /* standard header assumes linker command file definitions */ |
| #include <ti/apps/msp430/msp430x22x4.h> |
| #else |
| /* "pure-C" definitions below are sufficient for this module */ |
| #define IE2 (*(volatile int8_t *)0x0001) /* 8-bit */ |
| #define IFG2 (*(volatile int8_t *)0x0003) /* 8-bit */ |
| |
| #define DCOCTL (*(volatile int8_t *)0x0056) /* 8-bit */ |
| #define BCSCTL1 (*(volatile int8_t *)0x0057) /* 8-bit */ |
| #define BCSCTL3 (*(volatile int8_t *)0x0053) /* 8-bit */ |
| |
| #define CALDCO_8MHZ (*(volatile int8_t *)0x10FC) /* 8-bit */ |
| #define CALBC1_8MHZ (*(volatile int8_t *)0x10FD) /* 8-bit */ |
| |
| #define P1OUT (*(volatile int8_t *)0x0021) /* 8-bit */ |
| #define P1DIR (*(volatile int8_t *)0x0022) /* 8-bit */ |
| #define P3SEL (*(volatile int8_t *)0x001B) /* 8-bit */ |
| |
| #define UCA0CTL1 (*(volatile int8_t *)0x0061) /* 8-bit */ |
| #define UCA0BR0 (*(volatile int8_t *)0x0062) /* 8-bit */ |
| #define UCA0BR1 (*(volatile int8_t *)0x0063) /* 8-bit */ |
| #define UCA0MCTL (*(volatile int8_t *)0x0064) /* 8-bit */ |
| #define UCA0RXBUF (*(volatile int8_t *)0x0066) /* 8-bit */ |
| #define UCA0TXBUF (*(volatile int8_t *)0x0067) /* 8-bit */ |
| |
| #define WDTCTL (*(volatile int16_t *)0x120) /* 16-bit */ |
| |
| /* status register bits */ |
| #define GIE (0x0008) |
| #define CPUOFF (0x0010) |
| |
| #define LPM0_bits (CPUOFF) |
| |
| /* watch dog timer control register bit names */ |
| #define WDTPW (0x5A00) |
| #define WDTHOLD (0x0080) |
| |
| #define LFXT1S_2 (0x20) /* Mode 2 for LFXT1 : VLO */ |
| |
| #define UCSSEL_2 (0x80) /* USCI 0 Clock Source: 2 */ |
| #define UCBRS_2 (0x04) /* USCI Second Stage Modulation Select 1 */ |
| #define UCSWRST (0x01) /* USCI Software Reset */ |
| #define UCA0RXIE (0x01) /* USCI rx interrupt enable */ |
| |
| /* IFG2 bits */ |
| #define UCA0TXIFG (0x02) /* USCI tx flag bit */ |
| #endif |
| |
| /* |
| * ======== init ======== |
| */ |
| static void init(void) |
| { |
| WDTCTL = WDTPW + WDTHOLD; /* Stop watchdog timer */ |
| |
| P1DIR |= 0x03; /* Set P1.0,1 to output direction */ |
| P1OUT = 0; /* turn off LEDs */ |
| |
| #if USE_8MHZ |
| /* delay loop to ensure proper startup before increasing the DCO from the |
| * reset startup value of 1MHz. |
| * This is typically tailored to the power supply used, and in this case |
| * is overkill for safety due to wide distribution. |
| */ |
| {volatile int i; for (i = 0; i < 0xFFFF; i++){}} |
| |
| BCSCTL1 = CALBC1_8MHZ; /* Set DCO to the default of Simpliciti */ |
| DCOCTL = CALDCO_8MHZ; |
| BCSCTL3 |= LFXT1S_2; /* LFXT1 = VLO */ |
| #else |
| BCSCTL1 = CALBC1_1MHZ; /* Set DCO to 1MHz */ |
| DCOCTL = CALDCO_1MHZ; |
| #endif |
| |
| /* init the UART (see Table 15-4, Section 15.3.13 MSP430 User's guide) */ |
| P3SEL = 0x30; /* P3.4,5 = USCI_A0 TXD/RXD */ |
| UCA0CTL1 = UCSSEL_2; /* SMCLK */ |
| #if USE_8MHZ |
| UCA0BR0 = 0x41; /* 8MHz DCO 9600 (UCBRx = 833) */ |
| UCA0BR1 = 0x03; /* 8MHz DC0 9600 */ |
| UCA0MCTL = UCBRS_2; /* 8MHz DC0 Modulation (UCBRSx = 2: UCOS16 = 0, UCBRFx = 0) */ |
| #else |
| UCA0BR0 = 104; /* 1MHz DC0 9600 (@8MHz 9600, use 0x41) */ |
| UCA0BR1 = 0; /* 1MHz DC0 9600 (@8MHz 9600, use 0x03) */ |
| UCA0MCTL = UCBRS0; /* 1MHz DC0 Modulation (UCBRSx = 1: UCOS16 = 0, UCBRFx = 0) */ |
| #endif |
| |
| UCA0CTL1 &= ~UCSWRST; /* Initialize USCI state machine */ |
| IE2 |= UCA0RXIE; /* Enable USCI_A0 RX interrupt */ |
| |
| flash(GREEN, 50, 4); /* indicate the init is done */ |
| } |
| |
| /* |
| * ======== flash ======== |
| */ |
| static void flash(Int color, Int period, Int count) |
| { |
| if (period == FOREVER) { |
| P1OUT |= color; |
| return; |
| } |
| |
| while (count) { |
| volatile unsigned int i; /* volatile to prevent optimization */ |
| |
| P1OUT ^= color; /* toggle P1.1,0 using exclusive-OR */ |
| |
| for (i = period * 1000; i != 0; i--) { /* delay period */ |
| ; |
| } |
| |
| if (count > 0) { /* if count starts < 0, go forever */ |
| count--; |
| } |
| } |
| } |
| |
| /* |
| * ======== myPutc ======== |
| */ |
| static void myPutc(Char ch) |
| { |
| while (!(IFG2 & UCA0TXIFG)) { /* USCI_A0 TX buffer ready? */ |
| ; |
| } |
| |
| UCA0TXBUF = ch; /* TX -> ch */ |
| } |
| |
| /* |
| * ======== USCI0RX_ISR ======== |
| */ |
| __interrupt void USCI0RX_ISR(void) |
| { |
| char c; |
| |
| c = UCA0RXBUF; /* read the character */ |
| |
| if (SysUart_getLineFxn == NULL) { |
| return; |
| } |
| |
| if (SysUart_lineBuf == NULL) { |
| SysUart_getLineFxn(&c, 1); |
| return; |
| } |
| |
| if (c == '\n') { |
| SysUart_lineBuf[module->lineIdx] = 0; |
| SysUart_getLineFxn(SysUart_lineBuf, module->lineIdx); |
| module->lineIdx = 0; |
| } |
| else if (module->lineIdx < SysUart_lineSize) { |
| SysUart_lineBuf[module->lineIdx++] = c; |
| } |
| } |
| |
| __asm("\t.global USCI0RX_ISR"); |
| __asm("\t.sect \".usci_rx\""); |
| __asm("\t.align 2"); |
| __asm("_USCI0_rx_vector:\n\t.field USCI0RX_ISR, 16"); |