Greetings, im using a TM4C123GXL launchpad and the problem is the next.
Im trying to use the RXFF and TXFF interrupts to send and receive, but one of them is not executing very well, It can't identify the interrupt.
ulStatus doesn't get in the 0x04 (RXFF). I can't find the problem, it can't execute the interruption for RXFF. probably i dont undertand how it starts this interrupt.
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_gpio.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/pwm.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "driverlib/buttons.h"
#include "driverlib/adc.h"
#include "driverlib/timer.h"
#include "math.h"
#include "driverlib/ssi.h"
#include "driverlib/qei.h"
//*****************************************************************************
//
// Number of bytes to send and receive.
//
//*****************************************************************************
#define NUM_SSI_DATA 3
//*****************************************************************************
//
// Global variables used in interrupt handler and the main loop.
//
//*****************************************************************************
volatile unsigned long g_ulSSI2RXFF = 0, g_ulSSI2TXFF = 0;
uint32_t g_ulDataRx2[NUM_SSI_DATA];
uint32_t g_ulDataTx2[NUM_SSI_DATA];
int count;
//ADC
unsigned long canal_0_adc0, canal_1_adc0, canal_2_adc0, canal_3_adc0, canal_5_adc0; // ADC variables
uint32_t ulADC0Value[5];
uint32_t g_ulDataRx0[NUM_SSI_DATA];
uint32_t g_ulDataTx0[NUM_SSI_DATA];
//*****************************************************************************
//
// Interrupt handler for SSI2 peripheral in slave mode. It reads the interrupt
// status and if the interrupt is fired by a RX time out interrupt it reads the
// SSI2 RX FIFO and increments a counter to tell the main loop that RX timeout
// interrupt was fired.
//
//*****************************************************************************
void
SSI2IntHandler(void)
{
unsigned long ulStatus, ulIndex;
//
// Read interrupt status.
//
ulStatus = SSIIntStatus(SSI2_BASE, 1);
//
// Check the reason for the interrupt.
//
if(ulStatus & SSI_TXFF)
{
//
// Interrupt is because of RX time out. So increment counter to tell
// main loop that RX timeout interrupt occurred.
//
g_ulSSI2TXFF++;
//
// Read NUM_SSI_DATA bytes of data from SSI2 RX FIFO.
//
for(ulIndex = 0; ulIndex < NUM_SSI_DATA; ulIndex++)
{
SSIDataGet(SSI2_BASE, &g_ulDataRx2[ulIndex]);
}
SSIIntClear(SSI2_BASE, SSI_TXFF);
SSIIntDisable(SSI2_BASE, SSI_TXFF);
}
if(ulStatus & SSI_RXFF)
{
//
// Interrupt is because of RX time out. So increment counter to tell
// main loop that RX timeout interrupt occurred.
//
g_ulSSI2RXFF++;
//
// Read NUM_SSI_DATA bytes of data from SSI2 RX FIFO.
//
for(ulIndex = 0; ulIndex < NUM_SSI_DATA; ulIndex++)
{
SSIDataPut(SSI2_BASE, g_ulDataTx2[ulIndex]);
}
SSIIntClear(SSI2_BASE, SSI_RXFF);
SSIIntDisable(SSI2_BASE, SSI_RXFF);
}
//
// Clear interrupts.
//
//SSIIntClear(SSI2_BASE, ulStatus);
}
void
InitConsole(void)
{
//
// Enable GPIO port A which is used for UART0 pins.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
//
// Configure the pin muxing for UART0 functions on port A0 and A1.
// This step is not necessary if your part does not support pin muxing.
//
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
//
// Select the alternate (UART) function for these pins.
//
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
//
// Initialize the UART for console I/O.
//
UARTStdioConfig(0, 115200, 80000000);
}
void
InitSPI0(void)
{
//
// The SSI0 peripheral must be enabled for use.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
//
// For this example SSI0 is used with PortA[5:2]. GPIO port A needs to be
// enabled so these pins can be used.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
//
// Configure the pin muxing for SSI0 functions on port A2, A3, A4, and A5.
// This step is not necessary if your part does not support pin muxing.
//
GPIOPinConfigure(GPIO_PA2_SSI0CLK);
GPIOPinConfigure(GPIO_PA3_SSI0FSS);
GPIOPinConfigure(GPIO_PA4_SSI0RX);
GPIOPinConfigure(GPIO_PA5_SSI0TX);
//
// Configure the GPIO settings for the SSI pins. This function also gives
// control of these pins to the SSI hardware. Consult the data sheet to
// see which functions are allocated per pin.
// The pins are assigned as follows:
// PA5 - SSI0Tx
// PA4 - SSI0Rx
// PA3 - SSI0Fss
// PA2 - SSI0CLK
//
GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 |
GPIO_PIN_2);
//
// Configure and enable the SSI0 port for SPI master mode.
//
SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_2,
SSI_MODE_MASTER, 660000, 16);
//
// Enable the SSI0 module.
//
SSIEnable(SSI0_BASE);
}
void
InitSPI2(void)
{
//
// The SSI0 peripheral must be enabled for use.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);
//
// For this example SSI2 is used with PortH[7:4]. GPIO port H needs to be
// enabled so these pins can be used.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
//
// Configure the pin muxing for SSI2 functions on port H4, H5, H6 and H7.
// This step is not necessary if your part does not support pin muxing.
//
GPIOPinConfigure(GPIO_PB4_SSI2CLK);
GPIOPinConfigure(GPIO_PB5_SSI2FSS);
GPIOPinConfigure(GPIO_PB6_SSI2RX);
GPIOPinConfigure(GPIO_PB7_SSI2TX);
//
// Configure the GPIO settings for the SSI pins. This function also gives
// control of these pins to the SSI hardware. Consult the data sheet to
// see which functions are allocated per pin.
// The pins are assigned as follows:
// PH7 - SSI2Tx
// PH6 - SSI2Rx
// PH5 - SSI2Fss
// PH4 - SSI2CLK
//
GPIOPinTypeSSI(GPIO_PORTB_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 |
GPIO_PIN_4);
//
// Configure and enable the SSI2 port for SPI slave mode.
//
SSIConfigSetExpClk(SSI2_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_2,
SSI_MODE_SLAVE, 660000, 16);
//
// Enable the SSI2 module.
//
SSIEnable(SSI2_BASE);
}
void
ADCRead (uint32_t ulADC0Value[]){
ROM_ADCSequenceDisable(ADC0_BASE, 0);
ROM_ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0); // Maximum priority
ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0); // PE3 - canal 0
ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH1); // PE2 - canal 1
ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH2); // PE1 - canal 2
ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH3); // PE0 - canal 3
ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 4, ADC_CTL_CH5 | ADC_CTL_IE | ADC_CTL_END); // PD2 - canal 5
ROM_ADCSequenceEnable(ADC0_BASE, 0); //Enable Sequence0
ROM_ADCIntClear(ADC0_BASE, 0); // Clear ADC flag
ROM_ADCProcessorTrigger(ADC0_BASE, 0); //Trigger ADC in the processor
while(!ROM_ADCIntStatus(ADC0_BASE, 0, false)) {/*wait for conversion*/}
ROM_ADCSequenceDataGet(ADC0_BASE, 0, ulADC0Value); // Data to buffer
canal_0_adc0 = (ulADC0Value[0]); // Throttle
canal_1_adc0 = (ulADC0Value[1]); // Current sensor
canal_2_adc0 = (ulADC0Value[2]); // Axis X
canal_3_adc0 = (ulADC0Value[3]); // Axis Y
canal_5_adc0 = (ulADC0Value[4]); // Axis Z
}
void
Send (uint32_t ulDataTx0[]) {
unsigned long ulindex;
// Clear any pending interrupt
//
SSIIntClear(SSI2_BASE, SSI_TXFF);
UARTprintf("\n Sent:\n ");
for(ulindex = 0; ulindex < NUM_SSI_DATA; ulindex++)
{
UARTprintf("'%d' ", ulDataTx0[ulindex]);
SSIDataPut(SSI0_BASE, ulDataTx0[ulindex]);
}
while(SSIBusy(SSI0_BASE))
{
}
SSIIntEnable(SSI2_BASE, SSI_TXFF );
IntEnable(INT_SSI2);
//
// Wait for the SSI2 RXTO interrupt to fire and data read from RXFIFO.
//
while(g_ulSSI2TXFF == 0)
{
}
//
// Display indication that salve has receiving data.
//
UARTprintf("\nReceived:\n ");
//
// Display the 3 bytes of data that were read from RX FIFO.
//
for(ulindex = 0; ulindex < NUM_SSI_DATA; ulindex++)
{
UARTprintf("'%d' ", g_ulDataRx2[ulindex]);
}
SSIIntClear(SSI2_BASE, SSI_TXFF);
//SSIIntDisable(SSI2_BASE, SSI_TXFF);
}
void
Ask (void){
//uint32_t ulDataRx0[NUM_SSI_DATA];
unsigned long ulindex;
SSIIntClear(SSI2_BASE, SSI_RXFF);
UARTprintf("\n Asked:\n ");
SSIIntEnable(SSI2_BASE, SSI_RXFF );
IntEnable(INT_SSI2);
//
// Send 3 bytes of data.
//
for(ulindex = 0; ulindex < NUM_SSI_DATA; ulindex++)
{
SSIDataGet(SSI0_BASE, &g_ulDataRx0[ulindex]);
}
while(SSIBusy(SSI0_BASE))
{
}
//
// Wait for the SSI2 RXTO interrupt to fire and data read from RXFIFO.
//
while(g_ulSSI2RXFF == 0)
{
UARTprintf("wait\n");
}
for(ulindex = 0; ulindex < NUM_SSI_DATA; ulindex++)
{
UARTprintf("'%d' ", g_ulDataRx0[ulindex]);
}
SSIIntDisable(SSI2_BASE, SSI_TXFF | SSI_RXFF);
}
int
main(void)
{
uint32_t ulDataTx0[NUM_SSI_DATA];
uint32_t ulDataRx0[NUM_SSI_DATA];
//
// Set the clocking to run directly from the external crystal/oscillator.
ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
ROM_FPULazyStackingEnable();
ROM_FPUEnable();
// Configurar ADC_0
ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_HALF, 1); //
ROM_ADCHardwareOversampleConfigure(ADC0_BASE, 64); // 64 samples for each value
//
// Set up the serial console to use for displaying messages. This is
// just for this example program and is not needed for SSI operation.
//
InitConsole();
//
// Display the setup on the console.
//
UARTprintf("SSI ->\n");
UARTprintf(" Mode: SPI\n");
UARTprintf(" Data: 16-bit\n\n");
//
// Init SPI0 as master.
//
InitSPI0();
//
// Init SPI2 as slave.
//
InitSPI2();
//
// Read any residual data from the SSI port. This makes sure the receive
// FIFOs are empty, so we don't read any unwanted junk. This is done here
// because the SPI SSI mode is full-duplex, which allows you to send and
// receive at the same time. The SSIDataGetNonBlocking function returns
// "true" when data was returned, and "false" when no data was returned.
// The "non-blocking" function checks if there is any data in the receive
// FIFO and does not "hang" if there isn't. This might not be needed here.
//
while(SSIDataGetNonBlocking(SSI0_BASE, &ulDataRx0[0]))
{
}
//
// Enable RX timeout interrupt.
//
//SSIIntEnable(SSI2_BASE, SSI_TXFF);
//
// Read any residual data from the SSI port. This makes sure the receive
// FIFOs are empty, so we don't read any unwanted junk. This is done here
// because the SPI SSI mode is full-duplex, which allows you to send and
// receive at the same time. The SSIDataGetNonBlocking function returns
// "true" when data was returned, and "false" when no data was returned.
// The "non-blocking" function checks if there is any data in the receive
// FIFO and does not "hang" if there isn't.
//
while(SSIDataGetNonBlocking(SSI2_BASE, &g_ulDataRx2[0]))
{
}
//
// Clear any pending interrupt
//
SSIIntClear(SSI2_BASE, SSI_TXFF | SSI_RXFF);
SSIIntDisable(SSI2_BASE, SSI_TXFF | SSI_RXFF);
while(1)
{
ADCRead(ulADC0Value);
ulDataTx0[0] = ulADC0Value[0];
ulDataTx0[1] = count++;
ulDataTx0[2] = 46;
Send(ulDataTx0);
g_ulDataTx2[0] = 1;
g_ulDataTx2[1] = 2;
g_ulDataTx2[2] = 3;
Ask();
SysCtlDelay(10000000);
}
}
It get's stuck in the wait