Hi
Here is a compact answer for a bare-metal solution.
1. Enter the interrupt (place interrupt handler address in SRAM, set interrupt priority, enable interrupt in NVIC) using
fnEnterInterrupt(26, 11, interrupt_spi0_data_received);
2. Enable SPI interrupt (in peripheral so that it is asserted to the NVIC input) as well as configuring SPI peripheral generally
3. Send SPI data and handle the interrupts generated in the process. Reading the received data will clear the interrupt in your case.
The hander routine should be declared as a standard subroutine [void function(void)]
Details about fnEnterInterrupt():
- assumes interrupt table is in RAM, set by VECTOR_TABLE_OFFSET_REG = RAM_START_ADDRESS, for example to set table to start of SRAM.
- the routine accepts the ID of the interrupt in question (26 is SPI0 for K60, for example, but can change between derivates), an interrupt priority (0..15, where 0 is highest), plus a prointer to the handler.
- the code is (translate to register names in your headers if needed)
// Function used to enter processor interrupts
//
static void fnEnterInterrupt(int iInterruptID, unsigned char ucPriority, void (*InterruptFunc)(void))
{
unsigned long *ptrIntSet = IRQ0_31_SER_ADD;
unsigned char *ptrPriority = IRQ0_3_PRIORITY_REGISTER_ADD;
VECTOR_TABLE *ptrVect;
void ( **processor_ints )( void );
ptrVect = (VECTOR_TABLE *)(RAM_START_ADDRESS);
processor_ints = (void (**)(void))&ptrVect->processor_interrupts;
processor_ints += iInterruptID;
*processor_ints = InterruptFunc;
ptrIntSet += (iInterruptID/32);
*ptrIntSet = (0x01 << (iInterruptID%32)); // enable the interrupt
ptrPriority += iInterruptID;
*ptrPriority = (ucPriority << 4); // define the interrupt's priority
}
VECTOR_TABLE is defined as
typedef struct stVECTOR_TABLE
{
RESET_VECTOR reset_vect;
void (*ptrNMI)(void);
void (*ptrHardFault)(void);
void (*ptrMemManagement)(void);
void (*ptrBusFault)(void);
void (*ptrUsageFault)(void);
unsigned long ptrReserved1[4];
void (*ptrSVCall)(void);
void (*ptrDebugMonitor)(void);
unsigned long ptrReserved2;
void (*ptrPendSV)(void);
void (*ptrSysTick)(void);
PROCESSOR_IRQ processor_interrupts; // length is processor specific
} VECTOR_TABLE;
with
typedef struct stRESET_VECTOR
{
void *ptrResetSP; // initial stack pointer
void (*ptrResetPC)(void); // initial program counter
} RESET_VECTOR;
and
// Kinetis interrupts
//
typedef struct stPROCESSOR_IRQ
{
void (*irq_DMA0)(void); // 0
void (*irq_DMA1)(void); // 1
void (*irq_DMA2)(void); // 2
void (*irq_DMA3)(void); // 3
void (*irq_DMA4)(void); // 4
void (*irq_DMA5)(void); // 5
void (*irq_DMA6)(void); // 6
void (*irq_DMA7)(void); // 7
void (*irq_DMA8)(void); // 8
void (*irq_DMA9)(void); // 9
void (*irq_DMA10)(void); // 10
void (*irq_DMA11)(void); // 11
void (*irq_DMA12)(void); // 12
void (*irq_DMA13)(void); // 13
void (*irq_DMA14)(void); // 14
void (*irq_DMA15)(void); // 15
void (*irq_DMA_ERROR)(void); // 16
void (*irq_MCM)(void); // 17
void (*irq_FLASH_CC)(void); // 18
void (*irq_FLASH_RC)(void); // 19
void (*irq_LOW_VOLTAGE)(void); // 20
void (*irq_LL_wakeup)(void); // 21
void (*irq_WDOG)(void); // 22
void (*irq_RNGB)(void); // 23
void (*irq_I2C0)(void); // 24
void (*irq_I2C1)(void); // 25
void (*irq_SPI0)(void); // 26
void (*irq_SPI1)(void); // 27
void (*irq_SPI2)(void); // 28
void (*irq_CAN0_MESSAGE)(void); // 29
void (*irq_CAN0_BUS_OFF)(void); // 30
void (*irq_CAN0_ERROR)(void); // 31
void (*irq_CAN0_TX)(void); // 32
void (*irq_CAN0_RX)(void); // 33
void (*irq_CAN0_WAKE_UP)(void); // 34
void (*irq_CAN0_IMEU)(void); // 35
void (*irq_CAN0_LOST_RX)(void); // 36
void (*irq_CAN1_MESSAGE)(void); // 37
void (*irq_CAN1_BUS_OFF)(void); // 38
void (*irq_CAN1_ERROR)(void); // 39
void (*irq_CAN1_TX)(void); // 40
void (*irq_CAN1_RX)(void); // 41
void (*irq_CAN1_WAKE_UP)(void); // 42
void (*irq_CAN1_IMEU)(void); // 43
void (*irq_CAN1_LOST_RX)(void); // 44
void (*irq_UART0)(void); // 45
void (*irq_UART0_ERROR)(void); // 46
void (*irq_UART1)(void); // 47
void (*irq_UART1_ERROR)(void); // 48
void (*irq_UART2)(void); // 49
void (*irq_UART2_ERROR)(void); // 50
void (*irq_UART3)(void); // 51
void (*irq_UART3_ERROR)(void); // 52
void (*irq_UART4)(void); // 53
void (*irq_UART4_ERROR)(void); // 54
void (*irq_UART5)(void); // 55
void (*irq_UART5_ERROR)(void); // 56
void (*irq_ADC0)(void); // 57
void (*irq_ADC1)(void); // 58
void (*irq_CMP0)(void); // 59
void (*irq_CMP1)(void); // 60
void (*irq_CMP2)(void); // 61
void (*irq_FTM0)(void); // 62
void (*irq_FTP1)(void); // 63
void (*irq_FTP2)(void); // 64
void (*irq_CMT)(void); // 65
void (*irq_RTC_ALARM)(void); // 66
void (*reserved0)(void); // 67
void (*irq_PIT0)(void); // 68
void (*irq_PIT1)(void); // 69
void (*irq_PIT2)(void); // 70
void (*irq_PIT3)(void); // 71
void (*irq_PDB)(void); // 72
void (*irq_USB_OTG)(void); // 73
void (*irq_USB_CD)(void); // 74
void (*irq_ETH_IEEE1588)(void); // 75
void (*irq_ETH_TX)(void); // 76
void (*irq_ETH_RX)(void); // 77
void (*irq_ETH_ERR_MISC)(void); // 78
void (*irq_I2S)(void); // 79
void (*irq_SDHC)(void); // 80
void (*irq_DAC0)(void); // 81
void (*irq_DAC1)(void); // 82
void (*irq_TSI)(void); // 83
void (*irq_MCG)(void); // 84
void (*irq_LPT)(void); // 85
void (*reserved1)(void); // 86
void (*irq_PORTA)(void); // 87
void (*irq_PORTB)(void); // 88
void (*irq_PORTC)(void); // 89
void (*irq_PORTD)(void); // 90
void (*irq_PORTE)(void); // 91
} PROCESSOR_IRQ;
This is valid for K60 (for example) but the exact content is not actually important for just entering interrupts.
Regards
Mark