oPossum 1,083 Posted April 9, 2012 Share Posted April 9, 2012 This firmware will parse and display the TLV (tag length value) information stored in info segment A.Software serial (9600/8/N/1) is used so this will run on any G series chip.Output from G2452 showing DCO and ADC/temperature sensor calibrations. #include <msp430.h> volatile unsigned txdata = 0; #pragma vector = TIMER0_A0_VECTOR __interrupt void Timer0_A0(void) { if(txdata) { (txdata & 1) ? (CCTL0 &= ~OUTMOD2) : (CCTL0 |= OUTMOD2); txdata >>= 1; CCR0 += 104; } else { CCTL0 &= ~CCIE; } } void putc(const char c) { while(CCTL0 & CCIE); txdata = 0x0200 | (c << 1); CCR0 = TAR + 16; CCTL0 = OUTMOD0 | CCIE; } void print(const char *s) { while(*s) putc(*s++); } void print_hex_digit(unsigned n) { putc("0123456789ABCDEF"[n & 0x0F]); } void print_hex_byte(unsigned n) { print_hex_digit(n >> 4); print_hex_digit(n); } void print_hex_word(unsigned n) { print_hex_digit(n >> 12); print_hex_digit(n >> 8); print_hex_digit(n >> 4); print_hex_digit(n); } // TLV tags static const char * const tag_checksum[] = { "Checksum", 0 }; static const char * const tag_empty[] = { "TAG_EMPTY", 0 }; static const char * const tag_unknown[] = { "Unknown Tag", 0 }; static const char * const tag_dco[] = { "TAG_DCO_30", "CALBC1_16MHZ CALDCO_16MHZ", "CALBC1_12MHZ CALDCO_12MHZ", "CALBC1_8MHZ CALDCO_8MHZ", "CALBC1_1MHZ CALDCO_1MHZ", 0 }; static const char * const tag_adc[] = { "TAG_ADC1x_1", "CAL_ADC_GAIN_FACTOR", "CAL_ADC_OFFSET", "CAL_ADC_15VREF_FACTOR", "CAL_ADC_15T30", "CAL_ADC_15T85", "CAL_ADC_25VREF_FACTOR", "CAL_ADC_25T30", "CAL_ADC_25T85", 0 }; void dump_tlv_segment(const unsigned a, const unsigned n) { const unsigned * const s = (unsigned *)a; // Start of info segment const unsigned * const e = s + n; // End of info segment const char * const *tag = tag_checksum; // Segment begins with checksum unsigned len = 2; // Length of checksum unsigned chk = 0; // Init checksum // const unsigned *p; // for(p = s; p < e; ++p, len -= 2) { // Do segment const unsigned d = *p; // Get a word chk ^= d; // Update checksum if(!len) { // Next tag? len = 2 + (d >> 8); // Setup length of tag switch(d & 0xFF) { // Setup for tag type case 0x01: tag = tag_dco; break; // DCO cal case 0x08: tag = tag_adc; break; // ADC cal case 0xFE: tag = tag_empty; break; // Empty default: tag = tag_unknown; break; // Unknown } // } // print_hex_word((unsigned)p); // Address print(" "); // print_hex_word(d); // Data if(*tag) { // Tag print(" "); print(*tag); ++tag; // } // print("\r\n"); // } // chk ^= *s; // Fixup and validate checksum chk += *s; // //print_hex_word(chk); // print("Checksum is "); // if(chk) print("IN"); // print("valid\r\n"); // } void main(void) { WDTCTL = WDTPW | WDTHOLD; DCOCTL = 0; BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; CCTL0 = OUT; TACTL = TASSEL_2 | MC_2; P1SEL = BIT1; P1DIR = BIT1; __enable_interrupt(); print("Tag Length Value entries in Info Segment A\r\n"); dump_tlv_segment(0x10C0, 32); for (;; } bluehash, GeekDoc, tripwire and 1 other 4 Quote Link to post Share on other sites
Rickta59 589 Posted April 10, 2012 Share Posted April 10, 2012 I created an msp430-gcc port you can find here: https://gist.github.com/2348134. One thing I did change in the code, is how the defines related to TimerA serial output (TA0.0) are used. The original TI sample code uses defines that conceal what is really taking place. It hid the fact that all the code accomplished was to set and reset TA0.0 using the OUTMODx bits of the TACCTL0 register. In the original code, TI had used the defines OUTMOD0 and OUTMOD2. Although their code worked I didn't really understand why and just went with it. The correct defines for the OUTMODx bits are OUTMOD_0, OUTMOD_1 ... OUTMOD_7. I changed the ISR handler code to use to OUTMOD_1 and OUTMOD_5 so it is very obvious what is happening. To be honest I have no idea why you would use the OUTMOD0, OUTMOD1, or OUTMOD2 defines. -rick Quote Link to post Share on other sites
RobG 1,892 Posted April 10, 2012 Share Posted April 10, 2012 ...In the original code, TI had used the defines OUTMOD0 and OUTMOD2. Although their code worked I didn't really understand why and just went with it. The correct defines for the OUTMODx bits are OUTMOD_0, OUTMOD_1 ... OUTMOD_7. I changed the ISR handler code to use to OUTMOD_1 and OUTMOD_5 so it is very obvious what is happening. To be honest I have no idea why you would use the OUTMOD0, OUTMOD1, or OUTMOD2 defines. -rick BLAHx defines single bit, BLAH_x defines set of bits. So OUTMOD0 | OUTMOD2 = OUTMOD_5 Rickta59 and gordon 2 Quote Link to post Share on other sites
Rickta59 589 Posted April 10, 2012 Share Posted April 10, 2012 ...BLAHx defines single bit, BLAH_x defines set of bits. So OUTMOD0 | OUTMOD2 = OUTMOD_5 In my head, I was trying to map the bits from OUTMOD2 to the documentation and it never made sense why they weren't matching up. Now that you point it out, it is very obvious. I guess I should have looked at the actual bits in OUTMOD2 rather than wonder why they weren't what I expected. I now see that this convention is used throughout the headers... DIVS0, DIVS1 .. vs DIVS_0, DIVS_1,_DIVS_2, DIVS_3 .. SELM0 vs SELM_0 , UCBRF0 vs UCBRF_1.. UCBFR_15 Thanks that clears up a lot of confusion I should have noticed. -rick Quote Link to post Share on other sites
pabigot 355 Posted April 11, 2012 Share Posted April 11, 2012 To be honest I have no idea why you would use the OUTMOD0, OUTMOD1, or OUTMOD2 defines.-rick BLAHx defines single bit, BLAH_x defines set of bits. So OUTMOD0 | OUTMOD2 = OUTMOD_5 And two underscores for a symbolic name for the corresponding function, e.g.: #define TASSEL1 (0x0200) /* Timer A clock source select 1 */ #define TASSEL0 (0x0100) /* Timer A clock source select 0 */ #define TASSEL_0 (0x0000) /* Timer A clock source select: 0 - TACLK */ #define TASSEL_1 (0x0100) /* Timer A clock source select: 1 - ACLK */ #define TASSEL_2 (0x0200) /* Timer A clock source select: 2 - SMCLK */ #define TASSEL_3 (0x0300) /* Timer A clock source select: 3 - INCLK */ #define TASSEL__TACLK (0x0000) /* Timer A clock source select: 0 - TACLK */ #define TASSEL__ACLK (0x0100) /* Timer A clock source select: 1 - ACLK */ #define TASSEL__SMCLK (0x0200) /* Timer A clock source select: 2 - SMCLK */ #define TASSEL__INCLK (0x0300) /* Timer A clock source select: 3 - INCLK */ Though that's not available for all headers. You could file a bug to that effect on the mspgcc project and I'll push the enhancement upstream to TI; that might get it into all toolkits since they supply CCS and IAR as well. They were receptive to the request that TIMER0_A0_VECTOR be available on MCUs that formerly spelled it only asTIMERA0_VECTOR, which helps with portability across MCUs. oPossum, gordon and Rickta59 3 Quote Link to post Share on other sites
gordon 229 Posted April 11, 2012 Share Posted April 11, 2012 [TI] were receptive to the request that TIMER0_A0_VECTOR be available on MCUs that formerly spelled it only as TIMERA0_VECTOR, which helps with portability across MCUs. *hyperventilating* Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.