I've been working on some C++ template based classes and ran into a
snag. At first I thought it was related to the C++ templates however
it turns out when I reduced the code down to a straight 'C'
implementation I still have the same problem.

The code below has issues with the int8_t data type. In "test 2" i8
starts at 126 and incrementing it should make it roll over to a
negative number but it doesn't. This problem appears when i use -Os (
which is my normal mode of operation ) and does go away if I back off
and use -O1. If nothing else it would interesting if others try this
with their version of the compiler. I'm using the linux version that
ships with Energia:
gcc version 4.6.3 20120301 (mspgcc LTS 20120406 unpatched) (MSPGCC
20120406 (With patches: sf3540953 sf3559978)) Adding volatile to just
the int8_t declaration will get rid of the problem.

If you use msp430-gcc you might try this code and post your results.

Secondary question, red-hat has been churning away with the msp430-gcc
code for a while. Is there an ETA for when we might see a new version
from them?

Thanks,

-rick

code on github: https://gist.github.com/RickKimball/4957969

/**
 * signedtest.c - this fails to output int8_t values properly when
optimized with -Os
 *
 * Compiled like this:
 *
 * $ msp430-gcc -mmcu=msp430g2553 -DF_CPU=16000000 -Os -Wall \
 *   -Wno-main -g -mdisable-watchdog -fdata-sections -ffunction-sections \
 *   -Wl,--gc-sections signedtest.c
 *
 * $ mspdebug rf2500 "prog a.out"
 *
 * compiling with -O1 produces proper output, as does changing the
 * int8_t to volatile int8_t
 *
 */

#include <msp430.h>
#include <stdint.h>
#include <stdlib.h>

/**
 * serial output routines
 */
void printc(const char c) {
    while(!(IFG2 & UCA0TXIFG));
    IFG2 &= ~UCA0TXIFG;
    UCA0TXBUF = c;
}

void prints(const char *s) {
    while(*s)
      printc(*s++);
}

void printi(int8_t i) {
  char buff[8];

#if 1
  if ( i < 0 ) {
    printc('-');
    i=-i;
  }
  utoa((i & 0xff),buff,10);
#else
  itoa((int8_t)i,buff,10); /* also tried this, also failed */
#endif

  prints(buff);
}

void printu(uint8_t i) {
  char buff[8];

  utoa((i & 0xff),buff,10);
  prints(buff);
}

void println() {
  printc('\n');
}

static const uint32_t brd = (F_CPU + (9600 >> 1)) / 9600; // Bit rate divisor

int main(void) {
  uint16_t indx;

#define BAD

#if defined(GOOD)
  volatile int8_t i8; // test2 produces valid results
#elif defined(BAD)
  int8_t i8; // broken for test2 unless marked volatile or you use -O1
#endif
  uint8_t u8;

  WDTCTL = WDTPW + WDTHOLD;                       // No watchdog reset
                                                  //
  DCOCTL = 0;                                     // Run at 16 MHz
  BCSCTL1 = CALBC1_16MHZ;                         //
  DCOCTL  = CALDCO_16MHZ;                         //

  //P1DIR |= BIT0 | BIT4; P1SEL |= BIT4;

  // GPIO Configuration  ;                        // Set alternate
function I/O for UART & SPI
  P1SEL  |= BIT2;                                 // UART P1.2(tx)
  P1SEL2 |= BIT2;

  // Serial Config
  UCA0CTL1 = UCSWRST;                             // Hold USCI in
reset to allow configuration
  UCA0CTL0 = 0;                                   // No parity, LSB
first, 8 bits, one stop bit, UART (async)
  UCA0BR1 = (brd >> 12) & 0xFF;                   // High byte of whole divisor
  UCA0BR0 = (brd >> 4) & 0xFF;                    // Low byte of whole divisor
  UCA0MCTL = ((brd << 4) & 0xF0) | UCOS16;        // Fractional
divisor, oversampling mode
  UCA0CTL1 = UCSSEL_2;                            // Use SMCLK for bit
rate generator, release reset


  prints("-test 1- int8_t=125, uint8_t=125 - signed/unsigned boundary
rollover\n RESULTS: always succeeds\n");
  i8=125; u8=125;
  for(indx=0; indx < 5; indx++, i8++, u8++) {
    printi(i8);
    prints(", ");
    printu(u8);
    println();
  }

  prints("-test 2- int8_t=126, uint8_t=126 - signed/unsigned boundary
rollover\n RESULTS: fails unless volatile\n");
  i8=126; u8=126;
  for(indx=0; indx < 4; indx++, i8++, u8++) {
    printi(i8);
    prints(", ");
    printu(u8);
    println();
  }

  prints("-test 3- int8_t=127, uint8_t=127 - signed/unsigned boundary
rollover\n RESULTS: always ok\n");
  i8=127; u8=127;
  for(indx=0; indx < 3; indx++, i8++, u8++) {
    printi(i8);
    prints(", ");
    printu(u8);
    println();
  }

  while(1);
}

#if 0
>>> Bad results when int8_t not volatile

   -test 1- int8_t=125, uint8_t=125 - signed/unsigned boundary rollover
    RESULTS: always succeeds
   125, 125
   126, 126
   127, 127
   -128, 128
   -127, 129
   -test 2- int8_t=126, uint8_t=126 - signed/unsigned boundary rollover
    RESULTS: fails unless volatile
   126, 126
   127, 127
   127, 128 << fail this is the wrong result
   127, 129 << fail this is the wrong result
   -test 3- int8_t=127, uint8_t=127 - signed/unsigned boundary rollover
    RESULTS: always ok
   127, 127
   -128, 128
   -127, 129


>>> Good results when using volatile int8_t

  -test 1- int8_t=125, uint8_t=125 - signed/unsigned boundary rollover
   RESULTS: always succeeds
  125, 125
  126, 126
  127, 127
  -128, 128
  -127, 129
  -test 2- int8_t=126, uint8_t=126 - signed/unsigned boundary rollover
   RESULTS: fails unless volatile
  126, 126
  127, 127
  -128, 128
  -127, 129
  -test 3- int8_t=127, uint8_t=127 - signed/unsigned boundary rollover
   RESULTS: always ok
  127, 127
  -128, 128
  -127, 129


#endif

------------------------------------------------------------------------------
Free Next-Gen Firewall Hardware Offer
Buy your Sophos next-gen firewall before the end March 2013 
and get the hardware for free! Learn more.
http://p.sf.net/sfu/sophos-d2d-feb
_______________________________________________
Mspgcc-users mailing list
Mspgcc-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mspgcc-users

Reply via email to