2023-03-13 06:47 AM
Hi guys,
I using
keil uvisionV5.35.0.0
arm_compiler : V6.16
We are developing a project on STM32L071CZYx MCU. which has
flash memory: 192kB
RAM: 20KB
I have attached a I2C1_IRQhandler function for your reference.
void I2C1_IRQHandler(void)
{
I2C1->CR1 &= ~(I2C_CR1_RXIE |I2C_CR1_ADDRIE | I2C_CR1_STOPIE | I2C_CR1_TXIE);
switch((I2C1->ISR &(I2C_ISR_STOPF | I2C_ISR_ADDR |I2C_ISR_RXNE | I2C_ISR_TXIS)))
{
case 0x08: //address match
dev_addr = ((I2C1->ISR >> 16 ) & 0xFE); // assigning Recieved slave address
if(I2C1->ISR & I2C_ISR_DIR)
{
// Slave address with Read bit
if(i2c_state == I2C_GOT_CONTROL_WORD_ADDR)
{
i2c_state = I2C_REPEATED_START;
}
else
{
i2c_state = I2C_RD_STARTED;
}
__HAL_I2C_CLEAR_FLAG(&hi2c1,(I2C_FLAG_ADDR ));
I2C1->CR1 |= (I2C_CR1_TXIE); // enabling Transmitter Interrupt
//slave Tx
}
else
{
// Slave address with write bit
i2c_pkt_length = 0;
i2c_state = I2C_WR_STARTED;
__HAL_I2C_CLEAR_FLAG(&hi2c1,I2C_FLAG_ADDR);
I2C1->CR1 |= (I2C_CR1_RXIE); // stopIE is not required
//slave Rx
}
break;
case 0x04: //rx data for master
if(i2c_state == I2C_WR_STARTED)
{
CW =I2C1->RXDR;
word_addr = CW;
i2c_state = I2C_GOT_CONTROL_WORD_ADDR;
}
else
{
i2cdatarx[i2c_pkt_length++] = I2C1->RXDR;
i2c_state = I2C_DATA_STARTED;
}
__HAL_I2C_CLEAR_FLAG(&hi2c1,I2C_FLAG_RXNE);
I2C1->CR1 |= (I2C_CR1_RXIE | I2C_CR1_ADDRIE | I2C_CR1_STOPIE); // enabling Rx address match and Stop interrupt
break;
case 0x20: // detected a stop
if (dev_addr == 0xB0 )
{
if (i2c_state == I2C_DATA_STARTED || i2c_state == I2C_GOT_CONTROL_WORD_ADDR)
{
F0_write(word_addr);
}
else
{
I2C1->ISR |= I2C_ISR_TXE;//Setting flushing the TX buffer for new data transfer
}
}
else
{
if (i2c_state == I2C_DATA_STARTED || i2c_state == I2C_WR_STARTED)
{
if (mode == mFACTORY)
{
A0_write_FM(word_addr); // writting to sram and Eeprom
}
else
{
A0_write(word_addr);
}
}
else
{
I2C1->ISR |= I2C_ISR_TXE;//Setting flushing the TX buffer for new data transfer
}
}
i2c_state = I2C_IDLE;
__HAL_I2C_CLEAR_FLAG(&hi2c1,I2C_FLAG_STOPF);
I2C1->CR1 |= (I2C_CR1_ADDRIE); // enabling address match
break;
case 0x02: // Transmit has detected
//i2cdatarx = I2C_read_F0(CW);
if (dev_addr == 0xB0)
{
I2C1->TXDR = F0_Read(CW);
}
else
{
if (mode == 1)
{
I2C1->TXDR = A0_read_FM(CW);
}
else
{
I2C1->TXDR = A0_read(CW);
}
}
__HAL_I2C_CLEAR_FLAG(&hi2c1,(I2C_FLAG_ADDR));
I2C1->CR1 |= (I2C_CR1_STOPIE | I2C_CR1_TXIE);
break;
}
}
here I2C1 is configured has a slave.
without I2C_IRQ_handler function I2C1 will work well in polling mode.
Code crashes and lead to hardfault at hsc_dev_obj_init when I include I2C1_IRQ_handler function.
I have tried all the ways like increasing stack memory and reducing global variables but nothing works. please help me to resolve this error.
Regards,
Gopal Gowda
2023-03-13 07:48 AM
Hello @GR.5 ,
Please check the LR register content (in CPU registers), if :
If main stack => copy the @ in the main stack register and paste it in the memory view .
Copy the PC content and paste it in the disassembly viewer and see the instruction that cause the HardaFault
Foued
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2023-03-13 10:57 PM
Hi KHALSI_Foued Thanks for your reply,
As we can see above the LR register value is 0xFFFF-FFF9 and call stack local is showing hsc_dev_obj_init lead to the hardfault your suggesting that there is problem in handling main stack (may be stack overflow) so I have tried to increase the stack size and reduce the global variables in the program but still not working.
I don't know how I2C1_IRQ_handler is causing the problem?
Regards,
Gopal Gowda
2023-03-13 11:29 PM
Have a better routine to display registers at fault, and identify specific instructions involved.
2023-03-14 10:29 PM
Hi Tesla thanks for your reply,
I have attached a function at which I am getting Hardfault.
hsc_dev_t* hsc_dev_obj_init(struct hsc_dev_cls *dev, uint32_t asic_id)
{
/* Initialize */
HSC_MEMSET(dev, 0x0, sizeof(struct hsc_dev_cls));
dev->ops = NULL;
dev->asic_id = asic_id;
dev->pkg_type = 0;
return (hsc_dev_t*) dev;
}
But there won't be any crash in code if I don't add I2C1_IRQhandler function
only when I include I2C1_IRQhandler function It crashes.
I don't know How I2C1_IRQhandler function is responsible for crash.
Regards,
Gopal Gowda
2023-03-14 11:38 PM
Hi Krani thank you for reply,
can u elaborate please.
do you mean to display all the registers like R0 R1 R2 R3 R12 LR SP PC registers in the hard fault function.?
In Debug mode I executed step by step instructions when I try to execute
dev->ops = NULL of hsc_dev_obj_init function it is leading to hardfault.
2023-03-15 07:43 AM
Search these forums, or even the Keil website for fault handler code. @Community member has posted several (many????) of them here. Not just CPU registers but the memory management/fault registers.
Hmmm... I've never used uVision on ARM chips, but doesn't it have a fault analysis window somewhere in their IDE?
2023-03-15 09:11 AM
Sanity check the pointer "dev", ie its not NULL, misaligned, pointing outside of RAM
2023-03-15 09:18 AM
It does have something, not sure I've learned how to drive it. I know the MCU, I know my code, and I know what I'm looking for..
But, having useful output to a serial port is a force multiplier, it can be used to diagnose failures in the field, using very simple tools, and on large blocks of soak-test units it doesn't require debuggers/pods and infrastructure to the same degree to monitor/log units.
On a good day it can bracket the offending instruction, and I don't even need specific source
https://github.com/cturvey/RandomNinjaChef/blob/main/KeilHardFault.c