/* * XIOH power sequence * Copyright (C) 2013 Avencall * * serial.c - trace to serial console * WARNING: TRACES ARE NOT TO BE ACTIVATED FOR PRODUCTION FIRMWARES * (this .c file is guarded by TRACE_SERIAL) * Authors: * Guillaume Knispel * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /* - MSP_BSL_TXD and MSP_BSL_RXD are named according to their main role * on the board (potentially booting the MSP with a serial port), and * not according to their main low impedance physical connection to the * MSP430. In this software they will actually be used for the debugging * serial connection, unrelated with the standard MSP BSL function. */ #include "compiler.h" #include "config.h" #ifdef TRACE_SERIAL MASK_MISRA #include #include #include #include UNMASK_MISRA #include "def.h" #include "main.h" #include "hardware.h" #include "serial.h" /* # For UCOS16 = 0: def baud_slow(freq, ucbr, ucbrs): zeros = 8 - ucbrs return 1. / ((zeros * ucbr + ucbrs * (ucbr + 1)) / float(freq) / 8.) >>> baud_slow(2000000, 17, 3) 115107.91366906476 */ void SerialInit(void) { // Configure the USCI as an UART @ 115200 bauds // Precondition: SMCLK = 2MHz UCA0CTL1 |= UCSWRST; UCA0CTL0 = 0; // select UART mode and framing UCA0CTL1 = 0xC1; // UCSSEL=11b => SMCLK; (keep) UCSWRST = 1; UCA0BR0 = 17; UCA0BR1 = 0; UCA0MCTL = 0x06; // UCOS16=0; UCBRSx=3; UCBRFx=0 (dont care); UCA0STAT = 0; UCA0CTL1 &= ~UCSWRST; } #ifdef TEST_LOOP_SPEED u8 tl_delta = 0; s8 tl_state = 10; #define TL_UNKNOWN 0xFFFFu u16 tl_num = TL_UNKNOWN; u16 ref_Timer_A_count = 0; u16 tl_emit(void) { if (tl_state == TL_SAVED) { u16 value = tl_num | ((u16)tl_delta << 14); tl_num = TL_UNKNOWN; tl_state = TL_WAIT; return value; } else return 0xFFFFu; } #endif /* TEST_LOOP_SPEED */ static void serial_putchar(unsigned char c) { while (!(IFG2 & UCA0TXIFG)) ; /* nothing */ UCA0TXBUF = c; } /* like fputs, but hardcoded to serial output and can't fail */ void serial_puts(const char *s) { for (; *s; s++) { serial_putchar((unsigned char)*s); ResetSoftWD(); } } // TB_SIZE must be a power of 2 #define TB_SIZE 256 u8 trace_buffer[TB_SIZE]; u16 tb_beg = 0; u16 tb_fill = 0; static inline u16 TB_I(u16 raw_idx) { return raw_idx & (TB_SIZE - 1); } static void trace_byte(u8 val) { if (tb_fill == TB_SIZE) { tb_beg = TB_I(tb_beg + 1); tb_fill--; } trace_buffer[TB_I(tb_beg + tb_fill)] = val; tb_fill++; } void trace(u16 tstamp, u8 state, u8 infos) { trace_byte(tstamp >> 8); trace_byte(tstamp & 0xff); trace_byte(state); trace_byte(infos); } static inline char hex_nibble(u8 n) { return n + ((n > 9) ? 'a' - 10 : '0'); } static inline void dump_byte(char b[3], u8 n) { b[0] = hex_nibble(n >> 4); b[1] = hex_nibble(n & 0xf); b[2] = ' '; } void dump_trace(void) { static char buf[64]; u16 pos = 0; #define flush() \ do { \ buf[pos] = 0; \ serial_puts(buf); \ pos = 0; \ } while (0) u16 i; serial_puts("TRACE:\r\n"); pos = 0; for (i = 0; i < tb_fill; i++) { dump_byte(buf + pos, trace_buffer[TB_I(tb_beg + i)]); pos += 3; if ((i & 15) == 15) { buf[pos++] = '\r'; buf[pos++] = '\n'; } else if ((i & 7) == 7) { buf[pos++] = ' '; } if (pos >= 56) flush(); } flush(); if (i & 15) serial_puts("\r\n"); } static void trace_slps3n_changes(u8 state) { static u8 save_s3inreg = 0; u8 new_s3inreg = SLP_S3_N(inreg); if ((new_s3inreg ^ save_s3inreg) & SLP_S3_N(bit)) { trace(TRACE_WHAT(Timer_A_count, tl_emit()), state, new_s3inreg & SLP_S3_N(bit)); } save_s3inreg = new_s3inreg; } static void trace_tstamp_loop(u8 state) { static u16 save_timer_a_count = 0; u16 new_timer_a_count = Timer_A_count; u8 new_s3inreg = SLP_S3_N(inreg); if (new_timer_a_count < save_timer_a_count) { trace(TRACE_WHAT(new_timer_a_count, tl_emit()), state, new_s3inreg & SLP_S3_N(bit)); } save_timer_a_count = new_timer_a_count; } void trace_changes(u8 state) { trace_slps3n_changes(state); trace_tstamp_loop(state); } #endif /* TRACE_SERIAL */