Getting FreeRTOS running on PSOC5 (CY8C5888LTI-LP097)

So I’m trying to get FreeRTOS working on a PSOC5 microcontroller. It uses an ARM Cortex M3 CPU and has 64K of ram and 256K of flash. I’ve built my project by adding the source code files to an empty project and configuring the compiler to look for the right headers files as well as the port. I configured FreeRTOS to the best of my understanding using the website and I am able to make a task, but when starting the scheduler and going into pvrPortStartFirstTask, the system infinite loops in the interrupt default handler in the after the CY_BOOT_INT_DEFAULT_HANDLER_EXCEPTION_ENTRY_CALLBACK definition directive. The comments in the code even say that it should have never gotten there. I believe I have my interrupts set correctly but I’m not sure. I know that Cortex M3 and M4 cores have a reverse interrupt order and that the syscall interupt priority needs to be set to 191 because of the 3 most significant bits being the priority bits. I was wondering if the idle task being priority 0 was an issue, but the source code says that it shouldn’t be changed.

So I was wondering what the problem could be. Why would starting the first task cause the system to have problems? Is there something I should know about setting up FreeRTOS on a PSOC micro that I don’t?

Having multitasking working on this micro would be super cool. Thanks for any help!

It sounds like you have not installed the FreeRTOS interrupt handlers. See “Special note to ARM Cortex-M users” on this page.

So I read that part and added the following lines to my FreeRTOSConfig.h file:

#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

I believe the interrupt vector table is CMSIS compliant, but I’m not 100%. The rest of the generated source has some files with CMSIS in the name (cmsis_armcc.h, cmsis_compiler.h, and cmsis_gcc.h) so I feel like it should be. But it also says, " Using #defines in this way will only work if the default handlers provided by your development tools are defined as [weak symbols]." Admittedly, I don’t know how to check that on PSOC creator :sweat_smile:.

OR

It also says you can install the FreeRTOS defined xPortSysTickHandler(), xPortPendSVHandler() and vPortSVCHandler() functions on the SysTick, PendSV and SVCCall interrupt vectors. I’m have an idea of how to do this, but I’m not sure.

There is this function that takes a number corresponding to a specific interupt and an address for the routine and sets the interrupt vector. What I don’t know is what are the addresses of the routines? I know the function names and where they are defined, but I don’t know what to input if I was to use this function. Is there somewhere these address are shown? Perhaps in a #define that I missed?

/*******************************************************************************
    * Function Name: CyIntSetSysVector
    ****************************************************************************//**
    *  Sets the interrupt vector of the specified system interrupt number. System
    *  interrupts are present only for the ARM platform. These interrupts are for
    *  SysTick, PendSV and others.
    *
    *  \param number: System interrupt number:
    *    CY_INT_NMI_IRQN                - Non Maskable Interrupt
    *    CY_INT_HARD_FAULT_IRQN         - Hard Fault Interrupt
    *    CY_INT_MEM_MANAGE_IRQN         - Memory Management Interrupt
    *    CY_INT_BUS_FAULT_IRQN          - Bus Fault Interrupt
    *    CY_INT_USAGE_FAULT_IRQN        - Usage Fault Interrupt
    *    **CY_INT_SVCALL_IRQN             - SV Call Interrupt**
    *    CY_INT_DEBUG_MONITOR_IRQN      - Debug Monitor Interrupt
    *    **CY_INT_PEND_SV_IRQN            - Pend SV Interrupt**
    *    **CY_INT_SYSTICK_IRQN            - System Tick Interrupt**
    *
    *  \param address: Pointer to an interrupt service routine.
    *
    * \return
    *   The old ISR vector at this location.
    *
    *******************************************************************************/
    cyisraddress CyIntSetSysVector(uint8 number, cyisraddress address)
    {
        cyisraddress oldIsr;
        cyisraddress *ramVectorTable = *CY_INT_VECT_TABLE;

        CYASSERT(number <= CY_INT_SYS_NUMBER_MAX);

        /* Save old Interrupt service routine. */
        oldIsr = ramVectorTable[number & CY_INT_SYS_NUMBER_MASK];

        /* Set new Interrupt service routine. */
        ramVectorTable[number & CY_INT_SYS_NUMBER_MASK] = address;

        return (oldIsr);
    }

And if I was use this function to set the vectors, I would have to put this in main before I start the scheduler, right? Or does it need to be somewhere else?

Does your project have a file named something like startup_psoc5_[something].s? If so, it probably contains the vector table, which you can edit.

I found something like that.

In the file Cm3Start.c, there is this section where the RomVectors is defined and populated.

/*******************************************************************************
*
* Default Rom Interrupt Vector table.
*
*******************************************************************************/
#if defined(__ARMCC_VERSION)
    /* Suppress diagnostic message 1296-D: extended constant initialiser used */
    #pragma diag_suppress 1296
#endif  /* defined(__ARMCC_VERSION) */

#if defined (__ICCARM__)
    #pragma location=".romvectors"
    const intvec_elem __vector_table[CY_NUM_ROM_VECTORS] =
#else
    CY_SECTION(".romvectors")
    const cyisraddress RomVectors[CY_NUM_ROM_VECTORS] =
#endif  /* defined (__ICCARM__) */
{
    INITIAL_STACK_POINTER,   /* Initial stack pointer  0 */
    #if defined (__ICCARM__) /* Reset handler          1 */
        __iar_program_start,
    #else
        (cyisraddress)&Reset,
    #endif  /* defined (__ICCARM__) */
    &IntDefaultHandler,      /* NMI handler            2 */
    &IntDefaultHandler,      /* Hard fault handler     3 */
};

So here I would add three more elements to the array, right? To make it:

{
    INITIAL_STACK_POINTER,   /* Initial stack pointer  0 */
    #if defined (__ICCARM__) /* Reset handler          1 */
        __iar_program_start,
    #else
        (cyisraddress)&Reset,
    #endif  /* defined (__ICCARM__) */
    &IntDefaultHandler,      /* NMI handler            2 */
    &IntDefaultHandler,      /* Hard fault handler     3 */
    &xPortSysTickHandler, 
    &xPortPendSVHandler,
    &vPortSVCHandler    
};

I believe that’s correct, but I also have to increase the CY_NUM_ROM_VECTORS to 7. That would solve my initial issue. Though when I try to build, i get the following error coming out of multiple files:

Build error: 'ListItem_t {aka struct xLIST_ITEM}' has no member named 'pvContainer' 

Which is correct because the list item struct in list.h is as follows:

/*
 * Definition of the only type of object that a list can contain.
 */
struct xLIST;
struct xLIST_ITEM
{
    listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE           /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
    configLIST_VOLATILE TickType_t xItemValue;          /*< The value being listed.  In most cases this is used to sort the list in ascending order. */
    struct xLIST_ITEM * configLIST_VOLATILE pxNext;     /*< Pointer to the next ListItem_t in the list. */
    struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */
    void * pvOwner;                                     /*< Pointer to the object (normally a TCB) that contains the list item.  There is therefore a two way link between the object containing the list item and the list item itself. */
    struct xLIST * configLIST_VOLATILE pxContainer;     /*< Pointer to the list in which this list item is placed (if any). */
    listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE          /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
};
typedef struct xLIST_ITEM ListItem_t;                   /* For some reason lint wants this as two separate definitions. */

It has a member called pxContainer, but no pvContainer. I was wondering what was going on here. What do the v and the x mean? Why are they different?

So, whether I was supposed to or not, i simply renamed the member in the struct and it cleared that issue but now I’m having an error where it says there are multiple definitions of most of the functions in the port.c file. Which is weird because the functions are declared in portable.h and then defined in port.c.

Currently the error is:

Build error: multiple definition of `pxPortInitialiseStack'

But the declaration is here in this complex conditional directive in portable.h:

#if ( portUSING_MPU_WRAPPERS == 1 )
    #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
        StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
                                             StackType_t * pxEndOfStack,
                                             TaskFunction_t pxCode,
                                             void * pvParameters,
                                             BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION;
    #else
        StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
                                             TaskFunction_t pxCode,
                                             void * pvParameters,
                                             BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION;
    #endif
#else /* if ( portUSING_MPU_WRAPPERS == 1 ) */
    #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
        StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
                                             StackType_t * pxEndOfStack,
                                             TaskFunction_t pxCode,
                                             void * pvParameters ) PRIVILEGED_FUNCTION;
    #else
        StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
                                             TaskFunction_t pxCode,
                                             void * pvParameters ) PRIVILEGED_FUNCTION;
    #endif
#endif /* if ( portUSING_MPU_WRAPPERS == 1 ) */

and the definition is here in port.c:

StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
                                     TaskFunction_t pxCode,
                                     void * pvParameters )
{
    /* Simulate the stack frame as it would be created by a context switch
     * interrupt. */
    pxTopOfStack--;                                                      /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
    *pxTopOfStack = portINITIAL_XPSR;                                    /* xPSR */
    pxTopOfStack--;
    *pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
    pxTopOfStack--;
    *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS;             /* LR */
    pxTopOfStack -= 5;                                                   /* R12, R3, R2 and R1. */
    *pxTopOfStack = ( StackType_t ) pvParameters;                        /* R0 */
    pxTopOfStack -= 8;                                                   /* R11, R10, R9, R8, R7, R6, R5 and R4. */

    return pxTopOfStack;
}

So why does it say that there are multiple definitions?

Thanks so much for the help btw.

Can you share your FreeRTOSConfig.h? Are you setting configENABLE_BACKWARD_COMPATIBILITY to 1?

That is strange. Are you compiling only one port.c file? Can you share your MakeFile too?

Thanks.

I do have configENABLE_BACKWARD_COMPATIBILITY set to 1. However is it defined as 1 in FreeRTOS.h. This is my FreeRTOSConfig.h file:

/*
 * FreeRTOS V202107.00
 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * https://www.FreeRTOS.org
 * https://github.com/FreeRTOS
 *
 */

#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See https://www.freertos.org/a00110.html
*----------------------------------------------------------*/

#define configASSERT_DEFINED                             1
extern void vAssertCalled( void );
#define configASSERT( x )    if( ( x ) == 0 ) vAssertCalled()
#define configQUEUE_REGISTRY_SIZE                        20

#define configUSE_PREEMPTION                             1
#define configUSE_TIME_SLICING                           1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION          1

#define configUSE_IDLE_HOOK                              1
#define configUSE_TICK_HOOK                              1
#define configUSE_DAEMON_TASK_STARTUP_HOOK               0
#define configCPU_CLOCK_HZ                               ( ( unsigned long ) 24000000 )
#define configTICK_RATE_HZ                               ( ( TickType_t ) 1000 ) //1000 Hz OS tick
#define configMINIMAL_STACK_SIZE                         ( ( unsigned short ) 250 )
#define configTOTAL_HEAP_SIZE                            ( ( size_t ) ( 10000 ) )
#define configMAX_TASK_NAME_LEN                          ( 16 )
#define configUSE_TRACE_FACILITY                         0
#define configUSE_16_BIT_TICKS                           0
#define configIDLE_SHOULD_YIELD                          1
#define configUSE_CO_ROUTINES                            0

#define configMAX_PRIORITIES                             ( 10 )
#define configMAX_CO_ROUTINE_PRIORITIES                  ( 2 )
#define configTIMER_QUEUE_LENGTH                         20
#define configTIMER_TASK_PRIORITY                        ( configMAX_PRIORITIES - 1 )
#define configUSE_COUNTING_SEMAPHORES                    1
#define configSUPPORT_DYNAMIC_ALLOCATION                 1
#define configSUPPORT_STATIC_ALLOCATION                  0
#define  configNUM_TX_DESCRIPTORS                        15
#define configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN    2

/* Set the following definitions to 1 to include the API function, or zero
 * to exclude the API function. */

#define configUSE_MALLOC_FAILED_HOOK              1
#define configUSE_MUTEXES                         1
#define configUSE_RECURSIVE_MUTEXES               1
#define configUSE_TIMERS                          1
#define configTIMER_TASK_STACK_DEPTH              ( configMINIMAL_STACK_SIZE * 2 )

#define INCLUDE_vTaskPrioritySet                  1
#define INCLUDE_uxTaskPriorityGet                 1
#define INCLUDE_vTaskDelete                       1
#define INCLUDE_vTaskCleanUpResources             1
#define INCLUDE_vTaskSuspend                      1
#define INCLUDE_vTaskDelayUntil                   1
#define INCLUDE_vTaskDelay                        1
#define INCLUDE_uxTaskGetStackHighWaterMark       1
#define INCLUDE_uxTaskGetStackHighWaterMark2      1
#define INCLUDE_xTaskGetSchedulerState            1
#define INCLUDE_xTimerGetTimerDaemonTaskHandle    1
#define INCLUDE_xTaskGetIdleTaskHandle            1
#define INCLUDE_xTaskGetHandle                    1
#define INCLUDE_eTaskGetState                     1
#define INCLUDE_xSemaphoreGetMutexHolder          1
#define INCLUDE_xTimerPendFunctionCall            1
#define INCLUDE_xTaskAbortDelay                   1

unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */

#define projCOVERAGE_TEST                       0

#define configKERNEL_INTERRUPT_PRIORITY         255

/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
 * See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY    191 /* equivalent to 0xa0, or priority 5. */
#define configMAC_INTERRUPT_PRIORITY            5

/* Prototype for the function used to print out.  In this case it prints to the
 |     10 console before the network is connected then a UDP port after the network has
 |      9 connected. */
extern void vLoggingPrintf( const char * pcFormatString,
                            ... );

#ifdef HEAP3
    #define xPortGetMinimumEverFreeHeapSize    ( x )
    #define xPortGetFreeHeapSize               ( x )
#endif

#endif /* FREERTOS_CONFIG_H */

I’m not 100% on all the settings, so if you see something wrong please point it out to me.

Also I was able to solve the multiple definitions issue. Port.c defined xPortSysTickHandler, xPortPendSVHandler, and vPortSVCHandler, but the prototypes for the functions weren’t in portable.h, which is what FreeRTOS.h includes, not port.c. In my CM3Start.h file, where the interrupt vector is, I originally included port.c but then it didn’t see the prototype of the pxPortInitialiseStack function because of the include order. So I added the prototypes for the interupt functions in to portable.h and included FreeRTOS.h in the CM3Start.h file. This solved the issue where it said the interrupt functions were undefined, and the issue where there were multiple definitions of pxPortInitialiseStack. So that’s all good (I think).
However, now I’m back to square 1 :sweat_smile:. It’s doing the same thing in the first post, where it ends up in CY_ISR(IntDefaultHandler) after executing the prvPortStartFirstTask function. I would expect the interrupts to be set correctly since I added those functions in the vector table. I think I need to do something else to get the interrupts set properly. I’m not sure what.

Also this is my make file. I did copy files over from the demo application to a separate project after making. Maybe I missed something? I’m not completely sure what the make file is doing to set the interrupts, so that could be what I missed.

CC = arm-none-eabi-gcc
BIN := RTOSDemo.axf

BUILD_DIR := build

FREERTOS_DIR_REL := ../../../FreeRTOS
FREERTOS_DIR := $(abspath $(FREERTOS_DIR_REL))
KERNEL_DIR := $(FREERTOS_DIR)/Source

FREERTOS_PLUS_DIR_REL := ../../../FreeRTOS-Plus
FREERTOS_PLUS_DIR := $(abspath $(FREERTOS_PLUS_DIR_REL))

SOURCE_FILES += init/startup.c  syscall.c main.c
SOURCE_FILES += $(KERNEL_DIR)/portable/GCC/ARM_CM3/port.c
SOURCE_FILES += $(KERNEL_DIR)/tasks.c
SOURCE_FILES += $(KERNEL_DIR)/list.c
SOURCE_FILES += $(KERNEL_DIR)/queue.c
SOURCE_FILES += $(KERNEL_DIR)/timers.c
SOURCE_FILES += $(KERNEL_DIR)/event_groups.c
SOURCE_FILES += ${KERNEL_DIR}/portable/MemMang/heap_3.c

INCLUDE_DIRS += -I$(FREERTOS_DIR)/Demo/CORTEX_M3_MPS2_QEMU_GCC
INCLUDE_DIRS += -I$(FREERTOS_DIR)/Demo/CORTEX_M3_MPS2_QEMU_GCC/CMSIS
INCLUDE_DIRS += -I$(KERNEL_DIR)/include
INCLUDE_DIRS += -I$(KERNEL_DIR)/portable/GCC/ARM_CM3

ifeq ($(FULL_DEMO), 1)
    SOURCE_FILES += main_full.c
    SOURCE_FILES += $(KERNEL_DIR)/stream_buffer.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/AbortDelay.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/BlockQ.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/blocktim.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/countsem.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/death.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/dynamic.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/EventGroupsDemo.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/flop.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/GenQTest.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/integer.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/IntSemTest.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/MessageBufferAMP.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/MessageBufferDemo.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/PollQ.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/QPeek.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/QueueOverwrite.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/QueueSet.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/QueueSetPolling.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/recmutex.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/semtest.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/StaticAllocation.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/StreamBufferDemo.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/StreamBufferInterrupt.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/TaskNotify.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/TimerDemo.c
    SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Full/print.c

    INCLUDE_DIRS += -I$(FREERTOS_DIR)/Demo/Common/include
    INCLUDE_DIRS += -I${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/Include/

    CFLAGS := -DmainCREATE_FULL_DEMO_ONLY=1
else
    SOURCE_FILES += main_blinky.c

    CFLAGS := -DmainCREATE_SIMPLE_BLINKY_DEMO_ONLY=1
endif

DEFINES :=  -DQEMU_SOC_MPS2 -DHEAP3

LDFLAGS = -T ./scripts/mps2_m3.ld -specs=nano.specs --specs=rdimon.specs -lc -lrdimon
LDFLAGS += -Xlinker -Map=${BUILD_DIR}/output.map

CFLAGS += -nostartfiles -mthumb -mcpu=cortex-m3 -Wno-error=implicit-function-declaration
CFLAGS += -Wno-builtin-declaration-mismatch -Werror

ifeq ($(DEBUG), 1)
    CFLAGS += -ggdb3 -Og
else
    CFLAGS += -O3
endif
    CFLAGS += -fstrict-aliasing -Wstrict-aliasing -Wno-error=address-of-packed-member

OBJ_FILES := $(SOURCE_FILES:%.c=$(BUILD_DIR)/%.o)

CPPFLAGS += $(DEFINES)
CFLAGS += $(INCLUDE_DIRS)

.PHONY: clean

$(BUILD_DIR)/$(BIN) : $(OBJ_FILES)
	$(CC) -ffunction-sections -fdata-sections $(CFLAGS) $(LDFLAGS) $+ -o $(@)

%.d: %.c
	@set -e; rm -f $@; \
	$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
	sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
	rm -f $@.$$$$

INCLUDES := $(SOURCE_FILES:%.c=$(BUILD_DIR)/%.d)
-include $(INCLUDES)

${BUILD_DIR}/%.o : %.c Makefile
	-mkdir -p $(@D)
	$(CC) $(CFLAGS) $(CPPFLAGS) -MMD -c $< -o $@

clean:
	-rm -rf build

Thank you!

Edit: forgot to add makefile.

The vectors you added to the ROM vector table aren’t in the right place. They need to appear at specific indexes in the array.

If I were you I would remove them, and then I would call CyIntSetSysVector() three times prior to starting the scheduler, once for each vector FreeRTOS uses.

Jeff

This does not seem correct. You are not supposed to include a .c file!

If you are using the vector table from ROM, you need to edit your startup code to install FreeRTOS interrupt handlers. You can look for an example here: https://github.com/aws/amazon-freertos/blob/main/vendors/cypress/boards/CY8CKIT_064S0S2_4343W/aws_demos/application_code/cy_code/COMPONENT_CM4/TOOLCHAIN_ARM/startup_psoc6_02_cm4.s#L52

If you are moving vector table to RAM, then you need to call CyIntSetSysVector to install interrupt handlers.

Thanks.

Both of you are right! That was the issue. I had the correct thought in the beginning to use that function to add the interrupt routines. Seems like adding the routines straight to the vector table has a lot more steps. So I just added the following lines to the beginning of my main:

    CyIntSetSysVector(CY_INT_SVCALL_IRQN, &vPortSVCHandler);
    CyIntSetSysVector(CY_INT_PEND_SV_IRQN, &xPortPendSVHandler);
    CyIntSetSysVector(CY_INT_SYSTICK_IRQN, &xPortSysTickHandler);

And that did the trick. I had to swap out my CyDelays for task delays but after that it’s working great. Thanks for your help, you guys!