2020-01-10 08:16 AM
Hi,
I am using STM8 device as a SPI master and SMP580 is a slave. When I enable SPI Transmit Interrupt (SPI_ICR-> TXIE = 1) MCU is resetting and when not enable MCU reset not occurring. I am enabling these interrupt during MCU Init. MCU not reset when Rx interrupt is enabled.
My Observations are:
Please give your suggestions for how to use SPI transmit interrupt. Below is code for your reference.
#pragma vector = 0x0C // ToDo: To be checked
__interrupt void SPI_IRQHandler(void)
{
disableInterrupts();
if(SPIT_GetFlagStatus(SPI_SR_RXNE))
{
/* Receiving SPI Data */
temp = (uint8_t)(SPI->DR);
/* Clearing Receive FIFO drain request enable flag */
SPI_ClearFlag(SPI_SR_RXNE);
}
if(SPIT_GetFlagStatus(SPI_SR_TXE))
{
/* Transmit complete */
/* Clearing Receive FIFO drain request enable flag */
SPI_ClearFlag(SPI_SR_TXE);
}
enableInterrupts();
return;
}
void SPIT_ITConfig(uint8_t SPIT_IT, uint8_t NewState)
{
VAR(uint8_t, SPIT_VAR) itpos;
/* Get the SPI IT index */
itpos = (uint8_t)((uint8_t)1 << (uint8_t)((uint8_t)SPIT_IT & (uint8_t)0x0F));
if (NewState != SPIT_DISABLE)
{
SPI->ICR |= itpos; /* Enable interrupt*/
}
else
{
SPI->ICR &= (uint8_t)(~itpos); /* Disable interrupt*/
}
}
void SPIT_DeInit(void)
{
SPI->CR1 = ((uint8_t)0x00);
SPI->CR2 = ((uint8_t)0x00);
SPI->ICR = ((uint8_t)0x00);
SPI->SR = ((uint8_t)0x02);
SPI->CRCPR = ((uint8_t)0x07);
SPI_ClearFlag(SPI_SR_RXNE);
}
void SPIT_Init(void)
{
VAR(uint8_t, SPIT_VAR) SPIT_Loop = SPIT_ZERO;
SPIT_DeInit();
CLK->ICKR = 0; // Reset the Internal Clock Register.
CLK->ICKR |= CLK_ICKR_HSIEN; // Enable the HSI.
CLK->ECKR = 0; // Disable the external clock.
while (CLK_ICKR_HSIRDY == 0); // Wait for the HSI to be ready for use.
CLK->CKDIVR = 0; // Ensure the clocks are running at full speed.
CLK->PCKENR1 |= (uint8_t)((uint8_t)1 << ((uint8_t)SPIT_CLK_PERIPHERAL_SPI & (uint8_t)0x0F)); // Enable all peripheral clocks.
// CLK->CCOR = 1; // Turn on CCO.
CLK->HSITRIMR = 0; // Turn off any HSIU trimming.
CLK->SWIMCCR = 0; // Set SWIM to run at clock / 2.
CLK->SWR = 0xe1; // Use HSI as the clock source.
CLK->SWCR = 0; // Reset the clock switch control register.
CLK->SWCR |= CLK_SWCR_SWEN; // Enable switching.
while (CLK->SWCR & CLK_SWCR_SWBSY != 0); // Pause while the clock switch is busy.
/* Reset corresponding bit to GPIO_Pin in CR2 register */
GPIOC->CR2 &= (uint8_t)(~(SPIT_CFG_GPIOC_PIN));
GPIOE->CR2 &= (uint8_t)(~(SPIT_CFG_GPIOE_PIN));
/*-----------------------------*/
/* Input/Output mode selection */
/*-----------------------------*/
GPIOC->ODR |= (uint8_t)SPIT_CFG_GPIOC_PIN;
GPIOE->ODR |= (uint8_t)SPIT_CFG_GPIOE_PIN;
/* Set Output mode */
GPIOC->DDR |= (uint8_t)SPIT_CFG_GPIOC_PIN;
GPIOE->DDR |= (uint8_t)SPIT_CFG_GPIOE_PIN;
GPIOC->DDR &= (uint8_t)(~(SPIT_GPIOC_PIN_7_MISO));// Setting MISO Pin as Input
/*------------------------------------------------------------------------*/
/* Pull-Up/Float (Input) or Push-Pull/Open-Drain (Output) modes selection */
/*------------------------------------------------------------------------*/
GPIOC->CR1 |= (uint8_t)SPIT_CFG_GPIOC_PIN;
GPIOE->CR1 |= (uint8_t)SPIT_CFG_GPIOE_PIN;
/*-----------------------------------------------------*/
/* Interrupt (Input) or Slope (Output) modes selection */
/*-----------------------------------------------------*/
//GPIOC->CR2 |= (uint8_t)SPIT_CFG_GPIOC_PIN;
//GPIOC->CR2 |= (uint8_t)(SPIT_GPIOC_PIN_7_MISO);
GPIOE->CR2 |= (uint8_t)SPIT_CFG_GPIOE_PIN;
/* Frame Format, BaudRate, Clock Polarity and Phase configuration */
SPI->CR1 = (uint8_t)((uint8_t)((uint8_t)(uint8_t)0x00 | (uint8_t)0x18) |
(uint8_t)((uint8_t)(uint8_t)0x00 | (uint8_t)0x01));
/* Data direction configuration: BDM, BDOE and RXONLY bits */
SPI->CR2 = (uint8_t)((uint8_t)((uint8_t)0x00) | (uint8_t)((uint8_t)0x02));
SPI->CR2 |= (uint8_t)((uint8_t)0x01);
/* Master/Slave mode configuration */
SPI->CR1 |= (uint8_t)(0x04);
/* CRC configuration */
SPI->CRCPR = (uint8_t)0x00;
SPIT_ITConfig(((uint8_t)0x06),ENABLE);// Rx Interrupt Enable
SPIT_ITConfig(((uint8_t)0x07),ENABLE);// Tx Interrupt Enable
SPI->CR1 &= (uint8_t)(~((uint8_t)0x40));
/* Enable the SPI peripheral*/
SPI->CR1 |= ((uint8_t)0x40);
}
2020-01-15 01:15 AM
Enabling TXIE interrupt means that the interrupt will fire up as long as the tx buffer is empty. In the interrupt routine you need to actually write some data into the tx buffer or disable the interrupt. You cannot simply reset the TXE bit in SPI_SR, it is read only, and it tells you that the tx buffer is empty.
Your MCU resets because it executes continuously the SPI interrupt and you probably have a watchdog enabled.
2020-01-16 12:45 AM
In my current implementation at the time of SPI INIT I have made correction as follows,
When RXIE = 1 then I am writingdata to SR->DR = 0x00. After this line immediately again interrupt is called. Should i write the data to DR in ISR ?
if(SPIT_GetFlagStatus(SPI_SR_TXE))
{
SPIT_ITConfig(SPIT_ICR_TXEI,DISABLE);
//SPI->DR = 0x00;
}
if(SPIT_GetFlagStatus(SPI_SR_RXNE))
{
/* Receiving SPI Data */
Data_Read = (uint8_t)(SPI->DR);
Counter++;
if(Counter >= 0x2u)
{
/* Reset the Count and Length */
Counter = SPIT_ZERO;
status = (uint8_t)RX_COMPLETE;
// SPIT_ITConfig(SPIT_ICR_RXEI,DISABLE); /* Check it is required or not */
}
else
{
status = (uint8_t)SPIT_TX_INPROGRESS;
/* Write Next byte to transmit */
SPI->DR = 0x00;
}
}
Please let me know your suggestions .
2020-01-16 01:10 PM
It's quite clear you don't really understand how SPI bus works. It's better to take the time to understand the SPI interface and than write your code, instead of just trying to put together some C functions in the hope that something will work.
The manuals provide very good explanations, I suggest you read them thoroughly.
Good luck!