cancel
Showing results for 
Search instead for 
Did you mean: 

Discovery F4/STM32f407VG sometimes gets Stuck/Stoned

Bogdan
Senior
Posted on October 11, 2014 at 12:17

Hi guys, i am quite new to the ARM platform ( i think i have 6-7 months since i started playing with my ST board)

Yesturday i started working on a small library for BMP085 sensor. My whole work is done in C, using IAR compiler. The code works well, but my main concern is why after random periods 10-30 minutes, its stops.. if i reset from the button on the board, it works again... I had this isue even on other projects In the future i plan do make a little quadcopter using this discovery board, and i`m starting to get woried, supose its in the air, and the soft halts... Where is this halting comes? And how can i prevent such halts? Thanks This is my current project

#define rAddr 0xEF
#define wAddr 0xEE
int16_t AC1=8340;
int16_t AC2=-1232;
int16_t AC3=-14440;
int16_t AC4=-31743;
int16_t AC5=24449;//old 32757;
int16_t AC6=25123;// old 23153;
int16_t MB=-32768;
int16_t MC=-11075;// old -8711;
int16_t MD=2432;// old 2868;
int16_t B1=5498;
int16_t B2=67; 
char txt3[15];
char txt2[15];
char txt4[15];
void get_raw_pressure(){
int oss=3;
long UT,UP; 
i2c_send_cmd(wAddr,0xF4,0x2E);
delay_nms(5);
i2c_start_com();
i2c_wrAddr(wAddr); 
i2c_Wrbyte(0xF6); 
I2Cx->CR1 |= I2C_CR1_STOP;
i2c_start_com();
i2c_rdAddr(rAddr); 
uint8_t tMSB = i2c_rdAck(); 
uint8_t tLSB = i2c_rdNack();
UT=(tMSB<<
8
)+tLSB;
//
UT
=
27898
;
I2Cx->CR1 |= I2C_CR1_STOP;
//////////////////
i2c_send_cmd(wAddr,0xF4,(0x34+(oss<<
6
))); 
delay_nms(15);
i2c_start_com();
i2c_wrAddr(wAddr); 
i2c_Wrbyte(0xF6); 
I2Cx->CR1 |= I2C_CR1_STOP;
i2c_start_com();
i2c_rdAddr(rAddr); 
uint8_t hMSB = i2c_rdAck();
uint8_t lMSB = i2c_rdAck(); 
uint8_t LSB = i2c_rdNack();
I2Cx->CR1 |= I2C_CR1_STOP;
UP = ((hMSB<<
16
)+(lMSB<<8)+LSB)>>(8-oss);
long X1,X2,X3,B6,B3,B5;
unsigned long B4,B7;
long pp;
float tt;
X1=(UT-AC6)*AC5>>15;
X2=(MC<<
11
)/(X1+MD);
B5
=
X1
+X2;
tt=(B5+8)>>4;
tt /=10;
sprintf(txt2,''%f'',tt);
lcd_char(2,1,txt2);
///// presure calculation
B6=B5-4000;//-1600 k
X1=(B2*((B6*B6)>>12))>>11;// k
X2=(AC2*B6)>>11;//k
X3=X1+X2; //57 k
B3=(((AC1*4+X3)<<
oss
)+2)>>2;//k
X1=(AC3*B6)>>13;//k
X2=(B1*((B6*B6)>>12))>>16;
X3=((X1+X2)+2)>>2;
B4=(AC4*(uint32_t)(X3+32768))>>15;
B7=((uint32_t)(UP-B3)*(50000>>oss));
if(B7<
0x80000000
){pp=(B7<<1)/B4;} else { pp=(B7/B4)<<1;}//70003
X1=(pp>>8)*(pp>>8);
X1=(X1*3038)>>16;
X2=(-7357*pp)>>16;
int32_t pres=pp+((X1+X2+3791)>>4);
// pres /=100;
float hpa=pres/100; // convert pascal to hecta Pascal
//calculate altitude
float altitude = 1 - pow( (hpa/125),0.1903 );
altitude *= 44330;
sprintf(txt4,''%d'',pres);
lcd_char(1,1,txt4);
sprintf(txt3,''%f'',altitude);
lcd_char(3,1,txt3);
}
int main(void){
SystemInit();
SysTick_Init();
lcd_init();
Serial_I2c_Init();
while(1){
get_raw_pressure();
delay_nms(300);
}
}

#!colorado
6 REPLIES 6
stm322399
Senior
Posted on October 11, 2014 at 12:41

Hard to say exactly what your problem is.

I guess that the SW stay blocked inside one of the i2c function, probably a while waiting for a status register update. I2C very often requires software counter measures against bus lock.

Let your platform run under debugger and breaks when it become locked so you will know where to start debugging.

jj2
Associate II
Posted on October 11, 2014 at 17:50

Essentially agree w/poster Laurent - yet believe there's value in further detail.

I2C ''hang'' is classic problem yet can be removed from your analysis quickly/easily. Simply replace any/all calls to I2C w/(temporary) fixed values - and then exercise your program in a repetitive, looping basis. (neat to add a counter - to track the total) Should your issue disappear - I2C diagnosis appears spot on. If not - similar counters place @ each/every critical program function should identify ''what/where/when'' issue occurs. If it is I2C there are several well known methods to ''escape'' from a frozen loop - re-initialize the I2C peripheral - and re-launch your program. Sometimes just a short ''blast'' of I2C clocks will ''restore'' a confused I2C slave. (but not always - that's what's fun...) [edit] Just noted, your, ''

i2c_send_cmd

()'' is immediately followed by a fixed delay. This is non-standard/risky - is it not? Instead - shouldn't you be looping on some I2C test condition - insuring that the send_cmd properly executed - and/or completed?
Posted on October 11, 2014 at 18:10

Doesn't seem to be any error detection or handling going on here, what do you expect to happen when the world isn't perfect?

You should perhaps output and record telemetry information so you can understand how and why things go awry?
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Bogdan
Senior
Posted on October 11, 2014 at 19:02 Hello, just to clear some things with i2c, i've posted bellow the code for the custom i2c functions used to deal with BMP085 in the code from my first post

#include ''stm32f4xx_i2c.c''
#define GPIO_Pin_SCL GPIO_Pin_8
#define GPIO_Pin_SDA GPIO_Pin_9
#define I2Cx I2C1
void Serial_I2c_Init(){
GPIO_InitTypeDef GPIO_InitStruct;
I2C_InitTypeDef I2C_InitStructure; 
I2C_DeInit(I2Cx);
/* Enable I2C and GPIO clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); /* enable the peripheral clock for the pins used */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);/* enable APB1 peripheral clock for I2C1*/
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_SCL | GPIO_Pin_SDA;// | GPIO_RS232_TX | GPIO_RS232_RX ; ;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOB, &GPIO_InitStruct); 
//Pins modules asigment
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1); // SCL
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1); // SDA
/* I2C configuration */
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x00; 
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 400000;
I2C_DeInit(I2C1);
I2C_Init(I2Cx, &I2C_InitStructure);
I2C_Cmd(I2Cx, ENABLE); 
}
void i2c_start_com() {
/* check to see if data lines are idle or busy, if busy, loop till the line is free for other things :) */
//while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY)); // If busy flag is set loop, else continue 
I2C1->CR1 |= I2C_CR1_START; /* Start bit = 1 (generate start contidion) */
/* Check for MSL ( master bit mode if is set (1) or Not (0) */
while(!I2C_GetFlagStatus(I2C1,I2C_FLAG_MSL)); // If Master bit not set ( MSL=0, loop)
/* Check for SB (start bit if is SET (1) or Not (0) */
while(!I2C_GetFlagStatus(I2C1,I2C_FLAG_SB ));// if start bit not set (SB=0) , loop
I2C_ReadRegister(I2C1, I2C_Register_SR1); // reads the SR1 register
}
void i2c_wrAddr(uint8_t Address){
assert_param(IS_I2C_ALL_PERIPH(I2C1));
// assert_param(IS_I2C_DIRECTION(I2C_Direction));
/* Reset the address bit0 for write */
Address &= (uint8_t)~((uint8_t)I2C_OAR1_ADD0);
/* Send the address */
I2C1->DR = Address;//MPU_WR;
while(!I2C_GetFlagStatus(I2C1,I2C_FLAG_ADDR)); // if addr flag is not set or slave address not matched, l00p
I2C_ReadRegister(I2C1, I2C_Register_SR1); // reads the SR1 register
I2C_ReadRegister(I2C1, I2C_Register_SR2); // reads the SR2 register 
}
void i2c_rdAddr(uint8_t Address) {
assert_param(IS_I2C_ALL_PERIPH(I2C1));
/* Reset the address bit0 for write */
Address |= I2C_OAR1_ADD0;
/* Send the address */
I2C1->DR = Address;// old MPU_RD;
while(!I2C_GetFlagStatus(I2C1,I2C_FLAG_ADDR)); // if addr flag is not set or slave address not matched, l00p
I2C_ReadRegister(I2C1, I2C_Register_SR1); // reads the SR1 register
I2C_ReadRegister(I2C1, I2C_Register_SR2); // reads the SR2 register 
}
void i2c_Wrbyte(uint8_t byte) {
I2C1->DR = byte; 
while(!I2C_GetFlagStatus(I2C1,I2C_FLAG_TXE));
I2C_ClearFlag(I2C1, I2C_FLAG_TXE);
}
void i2c_send_cmd(uint8_t Adress,uint8_t regg, uint8_t databyte){
i2c_start_com();
i2c_wrAddr(Adress);
i2c_Wrbyte(regg);
i2c_Wrbyte(databyte);// 
I2Cx->CR1 |= I2C_CR1_STOP; /* Generate a STOP condition */
} 
static int i2c_rdAck(){
I2C_AcknowledgeConfig(I2C1, ENABLE);
while( !(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED )));//| I2C_FLAG_BTF)) ); // ev 7
return I2C_ReceiveData(I2C1); 
}
static int i2c_rdNack(){
I2C_AcknowledgeConfig(I2C1, DISABLE);
while( !(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED)));
return I2C_ReceiveData(I2C1);
}

jj2
Associate II
Posted on October 11, 2014 at 19:13

Just to clarify - Clive1 & this reporter - will ''thicken'' our tin-hats & try to avoid ground space below such ''challenged'' roto-copter...

Posted on October 11, 2014 at 22:46

A lot of unbounded while() loops in there, probably want some timeouts so they don't get stuck forever.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..