Jump to content
43oh

TLV data (calibration) parse and display


Recommended Posts

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.
post-2341-135135546239_thumb.png

#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 (;;
}
Link to post
Share on other sites

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

Link to post
Share on other sites
...

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

Link to post
Share on other sites
...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

Link to post
Share on other sites
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.

Link to post
Share on other sites

Join the conversation

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

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

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

×   Your previous content has been restored.   Clear editor

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

×
×
  • Create New...