FreeRTOS handlers not installed automatically without defines

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is more of an FYI I suppose. I spent hours trying to figure out why my FreeRTOS implementation wasn't functioning correctly because Atmel/FreeRTOS/the internet has basically no information about this define:

CONF_FREERTOS_USE_SPI

Using breakpoints, I managed to get to here (look for '// THIS LINE' near the middle)

status_code_t freertos_optionally_wait_transfer_completion(
		freertos_dma_event_control_t *dma_event_control,
		xSemaphoreHandle notification_semaphore,
		portTickType max_block_time_ticks)
{
	status_code_t return_value = STATUS_OK;

	if (notification_semaphore == NULL) {
		if (dma_event_control->transaction_complete_notification_semaphore !=
				NULL) {
			/* Wait until notified by the ISR that transmission is
			complete. */
			if (xSemaphoreTake(dma_event_control->  // THIS LINE
					transaction_complete_notification_semaphore,
					max_block_time_ticks) != pdPASS) {
				return_value = ERR_TIMEOUT;
			}
		}
	}

	return return_value;
}

After that statement executed, the CPU got stuck executing a dummy handler forever. Because the calling line referenced waiting on an ISR, I went looking for the handler and I happened to notice the block of interrupt handler definitions at the bottom of the freertos_spi_master.c file. NO WHERE is this mentioned in any documentation and the FreeRTOS Peripheral Control example doesn't have any of the defines in the entire project other than the aforementioned source file. After I put this in FreeRTOSConfig.h, everything started to work as expected:

#define CONF_FREERTOS_USE_SPI5

I'm assuming this is how the TWI and USART configurations need to be handled as well to work with FreeRTOS drivers. It's extremely frustrating that no one wrote this anywhere in the examples.

 

 

 

Note: Regarding the SPI peripherals, this is how I set it up:

    freertos_peripheral_options_t blocking_driver_options = {
        NULL,											/* This peripheral does not need a receive buffer, so this parameter is just set to NULL. */
        0,												/* There is no Rx buffer, so the rx buffer size is not used. */
        configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY,	/* The priority used by the SPI interrupts. */
        SPI_MASTER,										/* Communicating with the flash requires the peripheral to be configured as an SPI master. */
        (USE_TX_ACCESS_MUTEX | USE_RX_ACCESS_MUTEX | WAIT_TX_COMPLETE | WAIT_RX_COMPLETE)	/* The blocking driver is to be used, so WAIT_TX_COMPLETE and WAIT_RX_COMPLETE are set. */
    };
    freertos_spi = freertos_spi_master_init(DISPLAY_SPI, &blocking_driver_options);

    struct spi_device device;
    for(uint8_t i = 0 ; i < displays; i++) {
        device.id = i;
        spi_master_setup_device(DISPLAY_SPI, &device, SPI_MODE_0, DISPLAY_SPI_CLOCK_SPEED, 0);
    }
    spi_enable(DISPLAY_SPI);     

and this is how I use it:

    while(1) {
        for(int i = 0; i < 2; i++) {
            struct spi_device device = {.id = i};
            spi_select_device(DISPLAY_SPI, &device);
            ssd1306_sel_data();
            //spi_write_packet(DISPLAY_SPI,framebuffer[i], 128*64/8);
            freertos_spi_write_packet(freertos_spi, framebuffer[i], 128*8, 100);
            delay_us(SSD1306_LATENCY); // At least 3us
            spi_deselect_device(DISPLAY_SPI, &device);
        }
        vTaskDelayUntil(&xLastWakeTime, xDelayms);
    }