I configured my PolarFire SoC for SPI communication with SPI1 as the slave and SPI0 as the master. The MISO, MOSI, CLK, and CS of the master are connected to the MOSI, MISO, CLK, and CS of the slave, respectively.
This setup worked perfectly in baremetal. However, in FreeRTOS, an interrupt occurs after the clock signal is sent. Specifically, after pressing any key while the clock is connected, I receive an interrupt. If the clock is not connected, no interrupt occurs, but SPI requires the clock. Could you please advise on how to handle this interrupt issue?
Here is the code I used (modified from the existing demo application code for RISC-V):
/*******************************************************************************
* This project is used to to send command from spi0 (master) and receive
* corresponding response from spi1 (slave).
******************************************************************************/
/* Standard includes. */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
/* FreeRTOS kernel includes. */
#include <FreeRTOS.h>
#include <task.h>
#include <queue.h>
#include <semphr.h>
/* PolarFire HAL includes. */
#include "mpfs_hal/mss_hal.h"
#include "drivers/mss/mss_mmuart/mss_uart.h"
#include "drivers/mss/mss_spi/mss_spi.h"
/*-------------------------MACRO DEFINITIONS----------------------------------*/
#define COMMAND_BYTE_SIZE 1U
#define NB_OF_TURNAROUND_BYTES 4U
#define SLAVE_NB_OF_COMMANDS 4U
#define SLAVE_PACKET_LENGTH 8U
/* Priorities used by the tasks. */
#define SPI_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
#define UART_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
/*-----------------------FUNCTION DECLARATION---------------------------------*/
extern void freertos_vector_table( void );
void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName );
static void UART_Task( void *pvParameters );
static void SPI_Task( void *pvParameters );
static void spi1_slave_cmd_handler( uint8_t *, uint32_t );
static void spi0_block_rx_handler( uint8_t *, uint32_t );
static void mss_spi_overflow_handler( uint8_t mss_spi_core );
static void handle_trap1( void );
static void handle_trap2(void);
/*----------------------------------------------------------------------------*/
static const uint8_t g_separator[] ="\r\n\
------------------------------------------------------------------------------";
static uint8_t g_master_tx_buffer[5] = { 0x00, 0x01, 0x02, 0x03, 0xAA};
static uint8_t g_master_rx_buffer[8] = { 0u };
static uint8_t g_slave_rx_buffer[13] = { 0u };
uint8_t g_slave_tx_buffer[SLAVE_NB_OF_COMMANDS][SLAVE_PACKET_LENGTH] = {
{0x48, 0x41, 0x50, 0x50, 0x49, 0x4E, 0x45, 0x53},
{0x54, 0x52, 0x45, 0x41, 0x53, 0x55, 0x52, 0x45},
{0x43, 0x4F, 0x4D, 0x50, 0x55, 0x54, 0x45, 0x52},
{0x53, 0x4F, 0x4C, 0x49, 0x54, 0x55, 0x44, 0x45}
};
char g_ui_buf[100] = {0};
SemaphoreHandle_t xSemaphore = NULL;
/* Main function for the HART1(U54_1 processor). Application code running on
* HART1 is placed here. */
void e51( void )
{
/*Reset SPI0 and SPI1*/
(void)mss_config_clk_rst(MSS_PERIPH_SPI0, (uint8_t) MPFS_HAL_FIRST_HART, PERIPHERAL_ON);
(void)mss_config_clk_rst(MSS_PERIPH_SPI1, (uint8_t) MPFS_HAL_FIRST_HART, PERIPHERAL_ON);
(void)mss_config_clk_rst(MSS_PERIPH_MMUART0, (uint8_t) MPFS_HAL_FIRST_HART, PERIPHERAL_ON);
MSS_UART_init(&g_mss_uart0_lo,
MSS_UART_115200_BAUD,
MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
PLIC_init();
__enable_irq();
PLIC_SetPriority(SPI0_PLIC, 2u);
PLIC_SetPriority(SPI1_PLIC, 2u);
PLIC_EnableIRQ(SPI0_PLIC);
PLIC_EnableIRQ(SPI1_PLIC);
/* Initialize and configure SPI1 as master */
MSS_SPI_init(&g_mss_spi0_lo);
MSS_SPI_configure_master_mode(&g_mss_spi0_lo,
MSS_SPI_SLAVE_0,
MSS_SPI_MODE1,
256u,
MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE,
mss_spi_overflow_handler);
/* Initialize and configure SPI0 as slave */
MSS_SPI_init(&g_mss_spi1_lo);
MSS_SPI_configure_slave_mode(&g_mss_spi1_lo,
MSS_SPI_MODE1,
MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE,
mss_spi_overflow_handler);
MSS_SPI_set_slave_block_buffers(&g_mss_spi1_lo,
&g_slave_tx_buffer[0][0],
COMMAND_BYTE_SIZE + NB_OF_TURNAROUND_BYTES,
g_slave_rx_buffer,
sizeof(g_slave_rx_buffer),
spi0_block_rx_handler);
MSS_SPI_set_cmd_handler(&g_mss_spi1_lo,
spi1_slave_cmd_handler,
COMMAND_BYTE_SIZE);
__asm__ volatile( "csrw mtvec, %0" :: "r"( ( uintptr_t )freertos_vector_table | 0x1 ) );
/* Create binary semaphore */
xSemaphore = xSemaphoreCreateBinary();
if (xSemaphore == NULL) {
while(1); //Failed to create semaphore
}
/* Create UART Task */
xTaskCreate(UART_Task, "UART Task", configMINIMAL_STACK_SIZE, NULL, UART_TASK_PRIORITY, NULL);
/* Create SPI Task */
xTaskCreate(SPI_Task, "SPI Task", configMINIMAL_STACK_SIZE, NULL, SPI_TASK_PRIORITY, NULL);
/* Start the scheduler */
vTaskStartScheduler();
/* If all is well, the scheduler will now be running and the following line
* will never be reached. */
for (;;);
}
/*----------------------------------------------------------------------------*/
void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
{
( void ) pcTaskName;
( void ) pxTask;
/* Run time stack overflow checking is performed if
* configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
* function is called if a stack overflow is detected. */
taskDISABLE_INTERRUPTS();
for( ;; );
}
/*----------------------------------------------------------------------------*/
static void spi0_block_rx_handler
(
uint8_t * rx_buff,
uint32_t rx_size
)
{
/* SPI slave receive completion handler.
* This function is called by the SPI slave on the completion of each SPI
* transaction after the SPI chip select signal is de-asserted. */
}
/*----------------------------------------------------------------------------*/
static void spi1_slave_cmd_handler
(
uint8_t * rx_buff,
uint32_t rx_size
)
{
/* SPI slave command handler.
* This function is called by the SPI slave driver once the command byte is
* received. */
uint8_t index;
const uint8_t * p_response;
index = rx_buff[0];
if (index < SLAVE_NB_OF_COMMANDS)
{
p_response = &g_slave_tx_buffer[index][0];
}
else
{
p_response = &g_slave_tx_buffer[0][0];
}
MSS_SPI_set_cmd_response(&g_mss_spi1_lo, p_response, SLAVE_PACKET_LENGTH);
}
/*----------------------------------------------------------------------------*/
static void mss_spi_overflow_handler
(
uint8_t mss_spi_core
)
{
/* SPI buffer overflow handler
* This function is called by SPI driver in case of buffer overflow. */
if (mss_spi_core)
{
/* reset SPI1 */
(void)mss_config_clk_rst(MSS_PERIPH_SPI1, (uint8_t) MPFS_HAL_FIRST_HART, PERIPHERAL_OFF);
/* Take SPI1 out of reset. */
(void)mss_config_clk_rst(MSS_PERIPH_SPI1, (uint8_t) MPFS_HAL_FIRST_HART, PERIPHERAL_ON);
}
else
{
/* reset SPI0 */
(void)mss_config_clk_rst(MSS_PERIPH_SPI0, (uint8_t) MPFS_HAL_FIRST_HART, PERIPHERAL_OFF);
/* Take SPI0 out of reset. */
(void)mss_config_clk_rst(MSS_PERIPH_SPI0, (uint8_t) MPFS_HAL_FIRST_HART, PERIPHERAL_ON);
}
}
/*----------------------------------------------------------------------------*/
void UART_Task( void *pvParameters)
{
char key;
uint8_t rx_size;
uint8_t rx_buff[1];
for (;;) {
/* Prompt the user */
MSS_UART_polled_tx(&g_mss_uart0_lo, g_separator, sizeof(g_separator));
MSS_UART_polled_tx(&g_mss_uart0_lo, (const uint8_t*)"\r\n Press any key to continue.\r\n",
sizeof("\r\n Press any key to continue.\r\n"));
do
{
rx_size = MSS_UART_get_rx(&g_mss_uart0_lo, rx_buff, sizeof(rx_buff));
} while(0u == rx_size);
/* give the semaphore to notify the SPI task */
xSemaphoreGive(xSemaphore);
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
/******************************************************************************/
void SPI_Task( void *pvParameters)
{
uint8_t cmd_idx = 0U;
for (;;) {
/* Wait for the semaphore from UART Task */
if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
/* Assert slave select. */
MSS_SPI_set_slave_select(&g_mss_spi0_lo, MSS_SPI_SLAVE_0);
/* Perform block transfer */
MSS_SPI_transfer_block(&g_mss_spi0_lo,
g_master_tx_buffer,
COMMAND_BYTE_SIZE + NB_OF_TURNAROUND_BYTES,
g_master_rx_buffer,
sizeof(g_master_rx_buffer));
/* De-assert slave select. */
MSS_SPI_clear_slave_select(&g_mss_spi0_lo, MSS_SPI_SLAVE_0);
MSS_UART_polled_tx_string(&g_mss_uart0_lo, (const uint8_t*)"\r\nCommand sent to spi slave: ");
sprintf(g_ui_buf," %x \r\n", cmd_idx);
MSS_UART_polled_tx_string(&g_mss_uart0_lo, (const uint8_t*)&g_ui_buf);
MSS_UART_polled_tx_string(&g_mss_uart0_lo, (const uint8_t*)"\r\nData received from spi slave: ");
sprintf(g_ui_buf," %x %x %x %x %x %x %x %x \r\n",
g_master_rx_buffer[0],
g_master_rx_buffer[1],
g_master_rx_buffer[2],
g_master_rx_buffer[3],
g_master_rx_buffer[4],
g_master_rx_buffer[5],
g_master_rx_buffer[6],
g_master_rx_buffer[7]);
MSS_UART_polled_tx_string(&g_mss_uart0_lo, (const uint8_t*)&g_ui_buf);
/* Issue a different command each time to the slave.*/
if (3u == cmd_idx)
{
cmd_idx = 0u;
}
else
{
++cmd_idx;
}
g_master_tx_buffer[0] = cmd_idx;
}
}
}
/******************************************************************************/
void vAssertCalled( void )
{
taskDISABLE_INTERRUPTS();
}
/*-----------------------------------------------------------*/
void handle_trap1( void )
{
MSS_UART_polled_tx(&g_mss_uart0_lo, (const uint8_t*)"\r\n interrupt1.\r\n",
sizeof("\r\n interrupt1.\r\n "));
}
/*-----------------------------------------------------------*/
void handle_trap2( void )
{
MSS_UART_polled_tx(&g_mss_uart0_lo, (const uint8_t*)"\r\n interrupt2.\r\n",
sizeof("\r\n interrupt2.\r\n "));
}
/*-----------------------------------------------------------*/
void freertos_risc_v_application_interrupt_handler( uint32_t ulMcause )
{
char pcCause[ 20 ];
sprintf( pcCause, "\r\n %u \r\n", ulMcause );
MSS_UART_polled_tx_string(&g_mss_uart0_lo, (const uint8_t*)pcCause);
for(uint32_t i=0;i<2000000;i++)
{
}
handle_trap1();
}
/*-----------------------------------------------------------*/
void freertos_risc_v_application_exception_handler( uint32_t ulMcause )
{
char pcCause[ 20 ];
sprintf( pcCause, "%u", ulMcause );
MSS_UART_polled_tx_string(&g_mss_uart0_lo, (const uint8_t*)pcCause);
handle_trap2();
}
/*-----------------------------------------------------------*/
Output I am getting:
---------------------------------------------------------------------
Press any key to continue.
11
interrupt1.
11
interrupt1.
11
interrupt1.
11
interrupt1.
11
interrupt1.
11
interrupt1.
11
interrupt1.
11
interrupt1.
11
interrupt1.
11
interrupt1.
11