Hi
I am using a MSP430F2619 with IAR to make a data logger : I measure 3 voltages (from ADCXMEMO) which are written to a SD card. A user can ask those data to be sent thru the serial port. There are two interruptions : Timer A0 to increment seconds (a led is blinking each second) and USCIAB0RX to listen to the serial port if data is coming. I am using a library provided by Texas Instruments to access a MultiMediaCard (slaa281b). If I do not use the SD MMC card it is stable. If I use the SD MMC card, it hangs few hours later (but the led still blinks) ... I do not see what could be the problem ? and how to locate it ... I attach the code.
Thanks for any hint to help me to debug it.
Cheers Karim
#include "msp430x26x.h"
#include "msp430.h"
#include "hal_hardware_board.h"
#include "mmc.h"
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <intrinsics.h>
#define LENFORCOM 200
#define FREQ 120 // acquire every FREQ seconds
#define LENFORPARAMETERS 30
#define NUMBEROFPARAMETERS 10
unsigned int seconds=0,min=0,h=0,day=0,month=0,year=0;
unsigned int daysInMonth[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
unsigned char com[LENFORCOM]={ 0 };
short mode=1;
unsigned int m=0, okbeg=0,okend=0;
// for sd mmc
unsigned long cardSize = 0;
unsigned char status = 1;
unsigned int timeout = 0;
unsigned long numblocks=0;
unsigned long totalBlocks;
// timer initialisation
void initTimer()
{
P1DIR |= 0x01; // P1.0 output
TACTL = TASSEL_1 + MC_1 + ID_3; // Timer A mode control: 1 - Up to CCR0 clock source=ACLK input divider: /8
CCTL0 = CCIE; // CCR0 interrupt enabled
TACCR0 = 4000 ; // wake up every second
}
// initialisation uart 115200 bauds 8-N-1
void init_rs1_115200()
{
P1DIR |= 0x01;
BCSCTL1 = CALBC1_1MHZ; // Set DCO
DCOCTL = CALDCO_1MHZ;
P3SEL = 0x30; // P3.4,5 = USCI_A0 TXD/RXD
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 8; // 1MHz 115200
UCA0BR1 = 0; // 1MHz 115200
UCA0MCTL = UCBRS2 + UCBRS0; // Modulation UCBRSx = 5
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
}
// function to send a character on serial port
void snd_rs1(unsigned char cara)
{
while ((IFG2&UCA0TXIFG)==0);
UCA0TXBUF=cara;
}
// function to send a string on serial port
void str_rs1(unsigned char* cara)
{
int k=0;
do {snd_rs1(cara[k]);k++;} while (cara[k]!=0);
}
// initialisation of ADC 12bits
void init_ADC(void)
{
P6SEL = 0x08; // Enable A/D channel inputs
ADC12CTL0 = ADC12ON+MSC+SHT0_2; // Turn on ADC12, set sampling time
ADC12CTL1 = SHP+CONSEQ_1; // Use sampling timer, single sequence
ADC12MCTL0 = INCH_0; // ref+=AVcc, channel = A0
ADC12MCTL1 = INCH_1; // ref+=AVcc, channel = A1
ADC12MCTL2 = INCH_2+EOS; // ref+=AVcc, channel = A2, end seq.
ADC12CTL0 |= ADC12SC;
ADC12CTL0 |= ENC; // Enable conversions
//P6DIR &= 0x08; // P6.0, i/p
}
void initSDMMC()
{
unsigned char ch[200];
memset(ch,0,sizeof(ch));
// MMC/SD-card
while (status != 0) // if return in not NULL an error did occur and the
// MMC/SD-card will be initialized again
{
status = mmcInit();
timeout++;
if (timeout == 150) // Try 50 times till error
{
snprintf (ch,sizeof(ch),"No MMC/SD-card found!! %x\n", status);
str_rs1(ch);
break;
}
}
while ((mmcPing() != MMC_SUCCESS)); // Wait till card is inserted
}
// function to take data
void mesures(unsigned short *val)
{
ADC12CTL0|=ADC12SC; // start conversion
do {} while ((ADC12CTL1 & 1)!=0);
val[0] = ADC12MEM0; // Move results, IFG is cleared
val[1] = ADC12MEM1; // Move results, IFG is cleared
val[2] = ADC12MEM2; // Move results, IFG is cleared
}
void acquisition()
{
unsigned short T,H,Ct;
float temp, Vtemp, Vhum,hum,Vcurrent,current;
unsigned short results[3];
unsigned char chaine [200], buffer[512];
mesures(results);
// temperature
T=results[0];
Vtemp=((float)T*3.3/4095);
temp= Vtemp/0.04; //sensibilite capteur 40mV/°c
// Humidity
H=results[1];
Vhum=((float)H*3.3/4095);
hum=(Vhum+0.5)*(0.9237-0.0041*temp+0.00004*temp*temp)/(0.0305+0.000044*temp-0.0000011*temp*temp); //humi=f(temp)
// Current
Ct=results[2];
Vcurrent=((float)Ct*3.3/4095);
current=(Vcurrent-2.5)/0.20833; // mesure de courant
snprintf(chaine,sizeof(chaine),"%d-%d-%d %2d:%2d:%2d \t temperature= %.3f \t humidity=%.3f \t current=%.3f\n",year,month,day,h,min,seconds,temp,hum,current);
//str_rs1(chaine);
// store to mmc
initSDMMC();
memset(buffer,0,sizeof(buffer));
mmcReadSector(0, buffer);
//str_rs1(buffer);
numblocks=atoi(buffer);
numblocks++;
if ( numblocks > totalBlocks )
numblocks=0;
memset(buffer,0,sizeof(buffer));
snprintf(buffer,sizeof(buffer),"%ld",numblocks);
//str_rs1(buffer);
mmcWriteSector(0, buffer);
memset(buffer,0,sizeof(buffer));
snprintf(buffer,sizeof(buffer),"%d-%d-%d %2d:%2d:%2d \t temperature= %.3f \t humidity=%.3f \t current=%.3f\n",year,month,day,h,min,seconds,temp,hum,current);
mmcWriteSector(numblocks, buffer);
mmcGoIdle();
}
void acquisitionOnlySerial()
{
unsigned short T,H,Ct;
float temp, Vtemp, Vhum,hum,Vcurrent,current;
unsigned short results[3];
unsigned char chaine [200];
mesures(results);
// temperature
T=results[0];
Vtemp=((float)T*3.3/4095);
temp= Vtemp/0.04; //sensibilite capteur 40mV/°c
// Humidity
H=results[1];
Vhum=((float)H*3.3/4095);
hum=(Vhum+0.5)*(0.9237-0.0041*temp+0.00004*temp*temp)/(0.0305+0.000044*temp-0.0000011*temp*temp); //humi=f(temp)
// Current
Ct=results[2];
Vcurrent=((float)Ct*3.3/4095);
current=(Vcurrent-2.5)/0.20833; // mesure de courant
snprintf(chaine,sizeof(chaine),"|%d-%d-%d %2d:%2d:%2d \t temperature= %.3f \t humidity=%.3f \t current=%.3f\n",year,month,day,h,min,seconds,temp,hum,current);
str_rs1(chaine);
}
/////////////////////////////////////////////////
void main(void)
{
unsigned int nb[LENFORPARAMETERS],j,k;
unsigned char parameters[NUMBEROFPARAMETERS][LENFORPARAMETERS],ch[200],buffer[512];
unsigned int newFREQ;
unsigned long i,nbb,lines;
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
// initialisations
init_rs1_115200();
init_ADC();
initTimer();
initSDMMC();
// Read the Card Size from the CSD Register
cardSize = mmcReadCardSize();
memset(ch,0,sizeof(ch));
snprintf(ch,sizeof(ch),"%ld\n",cardSize);
str_rs1(ch);
totalBlocks=cardSize/512;
memset(ch,0,sizeof(ch));
snprintf(ch,sizeof(ch),"%ld\n",totalBlocks);
str_rs1(ch);
numblocks=0;
memset(buffer,0,sizeof(buffer));
snprintf(buffer,sizeof(buffer),"%ld",numblocks);
mmcWriteSector(0, buffer);
mmcGoIdle();
//////////////// main loop ////////////////////////
while(1)
{
_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/ interrupt
if ( FREQ <61 )
{
if ( seconds%FREQ == 0)
acquisition();
}
else if ( FREQ > 60 )
{
newFREQ=FREQ/60;
if ( min > 0 && min%newFREQ == 0 && seconds == 0)
acquisition();
}
switch(mode)
{
case 0 :
{
if ( okbeg == 1 && okend == 1 )
{
k=0;
for (j=0; j<LENFORPARAMETERS;j++)
nb[j]=0;
for (j=0; j<NUMBEROFPARAMETERS;j++)
memset(¶meters[j][0],0,sizeof(parameters[j]));
str_rs1(com);
for (j=0;j<strlen(com); j++)
{
if (com[j] != ';' && com[j] != '\0')
{
if ( k>0)
parameters[k][j-nb[k-1]]=com[j];
else
parameters[k][j]=com[j];
}
else
{
nb[k]=j+1;
if (k > 0)
parameters[k][j-nb[k-1]]='\0';
else
if (com[j] != ';')
parameters[k][j]=com[j];
k++;
}
}
for (j=0;j<=k;j++)
{
str_rs1(parameters[j]);
str_rs1("\r\n---\r\n");
}
memset(ch,0,sizeof(ch));
snprintf(ch,sizeof(ch),"got %d parameters\n",k);
str_rs1(ch);
// traitement
// k = number of values [com;val1;val2;...]
if ( strcmp(parameters[0],"st")==0 && k==6) // [st;y;m;d;h;min;secs] set time
{
str_rs1("\r\n set time \r\n");
year=atoi(parameters[1]);
month=atoi(parameters[2]);
day=atoi(parameters[3]);
h=atoi(parameters[4]);
min=atoi(parameters[5]);
seconds=atoi(parameters[6]);
// leap year
if ( year%4 == 0 && year%100 != 0 || year%400 == 0 )
daysInMonth[2] = 29;
else
daysInMonth[2] = 28;
str_rs1("\r\n new time set \r\n");
}
if ( strcmp(parameters[0],"re")==0 && k==1) // [re;1] read mmc card
{
str_rs1("\r\n readmmc \r\n");
initSDMMC();
memset(buffer,0,sizeof(buffer));
mmcReadSector(0, buffer);
nbb=atoi(buffer);
str_rs1(buffer);
for (i = 1; i < nbb; i++)
{
memset(buffer,0,sizeof(buffer));
mmcReadSector(i, buffer); // read a size Byte big block beginning at the address.
str_rs1(buffer);
}
mmcGoIdle();
str_rs1("\r\n readmmc done\r\n");
}
if ( strcmp(parameters[0],"gt")==0 && k==1) // [gt;1] get time
{
memset(buffer,0,512);
snprintf(buffer,sizeof(buffer),"%d-%d-%d %2d:%2d:%2d\n",year,month,day,h,min,seconds);
str_rs1(buffer);
}
if ( strcmp(parameters[0],"rs")==0 && k==1) // [rs;1] reset numblocks to 0
{
initSDMMC();
numblocks=0;
memset(buffer,0,sizeof(buffer));
snprintf(buffer,sizeof(buffer),"%ld",numblocks);
mmcWriteSector(0, buffer);
mmcGoIdle();
}
if ( strcmp(parameters[0],"rl")==0 && k==1) // [rl;N] read last N lines from SD MMC
{
str_rs1("\r\n readmmc last lines \r\n");
initSDMMC();
memset(buffer,0,sizeof(buffer));
mmcReadSector(0, buffer);
nbb=atoi(buffer);
str_rs1(buffer);
lines=atoi(parameters[1]);
for (i = nbb-lines; i < nbb; i++)
{
memset(buffer,0,sizeof(buffer));
mmcReadSector(i, buffer); // read a size Byte big block beginning at the address.
str_rs1(buffer);
}
mmcGoIdle();
str_rs1("\r\n readmmc last lines done\r\n");
}
if ( strcmp(parameters[0],"ac")==0 && k==1) // [ac;1] force acquisition and sends to serial port
{
acquisitionOnlySerial();
}
// fin traitement
k=0;
for (j=0; j<LENFORPARAMETERS;j++)
nb[j]=0;
for (j=0; j<NUMBEROFPARAMETERS;j++)
memset(¶meters[j][0],0,sizeof(parameters[j]));
mode=1;
okbeg=0;
okend=0;
memset(com,0,LENFORCOM);
*com='\0';
m=0;
}
if ( m >= LENFORCOM )
{
memset(com,0,LENFORCOM);
*com='\0';
m=0;
}
break;
}
default: break;
}
}
}// end of main
// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
P1OUT ^= 0x01; // Toggle P1.0
seconds++;
if (seconds==60)
{
seconds=0;
min++;
}
if (min==60)
{
min=0;
h++;
}
if (h==24)
{
h=0;
day++;
}
if ( day == daysInMonth[month] )
{
month++;
day=1;
}
if ( month == 12 )
{
month=1;
year++;
// leap year
if ( year%4 == 0 && year%100 != 0 || year%400 == 0 )
daysInMonth[2] = 29;
else
daysInMonth[2] = 28;
}
_BIC_SR_IRQ(LPM0_bits);
}
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USC0RX_ISR(void)
{
while (!(IFG2&UCA0RXIFG));
if ( UCA0RXBUF == '[' )
okbeg=1;
if ( UCA0RXBUF == ']' )
okend=1;
if ( okbeg == 1 && UCA0RXBUF != ']' && UCA0RXBUF != '[')
{
com[m]=UCA0RXBUF;
m++;
mode=0;
}
_BIC_SR_IRQ(LPM0_bits);
}