Tool/software: TI-RTOS
Hello,
I'm experimenting with using the DRV library directly for bare metal applications instead of using the SYS/BIOS on the keystone 2 K2H evaluation kit processor, with the PDK. I took one of the examples that supported bare metal -- a blinky project that used gpio interrupts -- and tested it.
With sys/bios everything works fine. However, as soon as I switch over to its bare metal version, when the gpio interrupt occurs the program hangs as it gets stuck in the undefined instruction region. The example was said to support bare metal, so I didn't do much to modify the example. The example works just fine bare metal without interrupts -- I tested it by simply commenting out the lines that enabled said interrupt -- but is there more extensive modifications I have to make in order to get gpio interrupts working with this example, such as implementing a peripheral ISR table myself or something?
The code is below.
/** * \file main.c * * \brief Example application main file. This application will toggle the led. * The led toggling will be done inside an callback function, which * will be called by Interrupt Service Routine. Interrupts are * triggered manually and no external source is used to trigger * interrupts. * */ /* * Copyright (C) 2014 - 2016 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #define BARE_METAL I put this define in #ifndef BARE_METAL /* XDCtools Header files */ #include <xdc/std.h> #include <xdc/cfg/global.h> #include <xdc/runtime/System.h> #include <xdc/runtime/Error.h> #endif /* BIOS Header files */ //#include <ti/sysbios/BIOS.h> #//include <ti/sysbios/knl/Task.h> #include <stdio.h> #include <ti/csl/csl_sem.h> #include <ti/csl/csl_semAux.h> /* TI-RTOS Header files */ #include <ti/drv/gpio/GPIO.h> #include <ti/drv/gpio/soc/GPIO_soc.h> #include "ti/drv/gpio/test/led_blink/src/GPIO_log.h" #include "ti/drv/gpio/test/led_blink/src/GPIO_board.h" /********************************************************************** ************************** Macros ************************************ **********************************************************************/ #if defined(SOC_AM572x) || defined (SOC_AM571x) #if defined (__TI_ARM_V7M4__) #define DELAY_VALUE (0x6FFFFFU) /* Update Delay as it is not sufficent for M4 core */ #else #define DELAY_VALUE (0x6FFFFFU) #endif #else #define DELAY_VALUE (0x6FFFFFU) #endif /********************************************************************** ************************** Internal functions ************************ **********************************************************************/ /* Delay function */ void AppDelay(unsigned int delayVal); /* Callback function */ void AppGpioCallbackFxn(void); #if defined(idkAM572x) || defined(idkAM571x) /* GPIO clock and pinmux configurations */ extern void AppGPIOInit(void); #endif #if defined(idkAM572x) extern void GPIOApp_UpdateBoardInfo(void); extern void GPIOAppUpdateConfig(uint32_t *gpioBaseAddr, uint32_t *gpioPin); #endif /* * ======== Board_initGPIO ======== */ static void Board_initGPIO(void) { Board_initCfg boardCfg; GPIO_v0_HwAttrs gpio_cfg; // Get the default SPI init configurations GPIO_socGetInitCfg(GPIO_LED0_PORT_NUM, &gpio_cfg); // Modify the default GPIO configurations if necessary // Set the default GPIO init configurations GPIO_socSetInitCfg(GPIO_LED0_PORT_NUM, &gpio_cfg); boardCfg = BOARD_INIT_PINMUX_CONFIG; Board_init(boardCfg); #if defined(idkAM572x) GPIOApp_UpdateBoardInfo(); #endif } /********************************************************************** ************************** Global Variables ************************** **********************************************************************/ volatile uint32_t gpio_intr_triggered = 0; uint32_t gpioBaseAddr; uint32_t gpioPin; /* * ======== test function ======== */ #ifndef BARE_METAL void gpio_test(UArg arg0, UArg arg1) { #else void main() { Board_initGPIO(); #endif uint32_t testOutput = 1; /* GPIO initialization */ GPIO_init(); /* Set the callback function */ GPIO_setCallback(USER_LED0, AppGpioCallbackFxn); /* Enable GPIO interrupt on the specific gpio pin */ GPIO_enableInt(USER_LED0); /* Write high to gpio pin to control LED1 */ GPIO_write((USER_LED1), GPIO_PIN_VAL_HIGH); AppDelay(DELAY_VALUE); //GPIO_log("\n GPIO Led Blink Application \n"); while(1) { GPIO_toggle(USER_LED0); AppDelay(DELAY_VALUE); if (testOutput) { //GPIO_log("\n All tests have passed \n"); testOutput = 0; } } #endif //Task_exit(); } #ifndef BARE_METAL /* * ======== main ======== */ int main(void) { /* Call board init functions */ Board_initGPIO(); /* Start BIOS */ BIOS_start(); return (0); } #endif /* * ======== AppDelay ======== */ void AppDelay(unsigned int delayVal) { while(delayVal) { delayVal--; } } /* * ======== Callback function ======== */ int i = 0; void AppGpioCallbackFxn(void) { /* Toggle LED1 */ i += 1; GPIO_toggle(USER_LED1); AppDelay(DELAY_VALUE); gpio_intr_triggered = 1; //System_printf("Blink: %d\n", i); //System_flush(); } Using the followng load script and startup files:
/****************************************************************************/
/* 66AK2Gxx.lds */
/* Copyright (c) 2016 Texas Instruments Incorporated */
/* Author: Rafael de Souza */
/* */
/* Description: This file is a sample linker command file that can be */
/* used for linking programs built with the GCC compiler */
/* and running the resulting .out file on a 66AK2Gxx device.*/
/* Use it as a guideline. You will want to */
/* change the memory layout to match your specific */
/* target system. You may want to change the allocation */
/* scheme according to the size of your program. */
/* */
/****************************************************************************/
MEMORY
{
MSMC_SRAM : o = 0x0C000000, l = 0x00100000 /* 1MB MSMC Shared SRAM */
DDR0 : o = 0x80000000, l = 0x80000000 /* 2GB external DDR0 */
}
/* Linker script to place sections and symbol values. Should be used together
* with other linker script that defines memory region DDR0.
* It references following symbols, which must be defined in code:
* Entry : Entry of reset handler
*
* It defines following symbols, which code can use without definition:
* __exidx_start
* __exidx_end
* __etext
* __data_start__
* __preinit_array_start
* __preinit_array_end
* __init_array_start
* __init_array_end
* __fini_array_start
* __fini_array_end
* __data_end__
* __bss_start__
* __bss_end__
* __end__
* end
* __HeapLimit
* __HeapBase - To be compatible with Linaro's semihosting support
* __StackLimit
* __StackTop
* __StackBase - To be compatible with Linaro's semihosting support
* __stack
*/
ENTRY(Entry)
SECTIONS
{
.rsthand :
{
. = ALIGN(0x10000);
KEEP(*(.isr_vector))
*startup_ARMCA15.o (.text)
} > MSMC_SRAM
. = ALIGN(4);
.text :
{
*(.text*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
KEEP(*(.eh_frame*))
} > MSMC_SRAM
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > MSMC_SRAM
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > MSMC_SRAM
__exidx_end = .;
.data :
{
. = ALIGN(4);
__data_start__ = .;
*(vtable)
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);
/* All data end */
__data_end__ = .;
} > MSMC_SRAM
.bss :
{
. = ALIGN(4);
__bss_start__ = .;
*(.bss*)
*(COMMON)
__bss_end__ = .;
} > MSMC_SRAM
.heap (NOLOAD):
{
/* The line below can be used to FILL the memory with a known value and
* debug any stack overruns. For this to work, the specifier (NOLOAD) above
* must be removed at the expense of an increase in the output binary size */
FILL(0xDEADBEEF)
. = ALIGN(4);
__end__ = .;
end = __end__;
/* The line below created to be compatible with Linaro's semihosting support */
__HeapBase = __end__;
*(.heap*)
. = . + HEAPSIZE;
__HeapLimit = .;
} > MSMC_SRAM
/* .stack section doesn't contain any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later */
.stack (NOLOAD):
{
/* The line below can be used to FILL the memory with a known value and
* debug any stack overruns. For this to work, the specifier (NOLOAD) above
* must be removed at the expense of an increase in the output binary size */
FILL(0xBAD0BAD0)
. = ALIGN(4);
__StackLimit = . ;
*(.stack*)
. = . + STACKSIZE;
__StackTop = . ;
/* The line below created to be compatible with Linaro's semihosting support */
__StackBase = . ;
} > MSMC_SRAM
PROVIDE(__stack = __StackTop);
}
/**************************************************************************/
@****************************************************************************** @ @ startup_ARMCA15.S - Init code routine for Cortex A15 cores and Linaro baremetal @ @****************************************************************************** @ @ Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ @ (Rafael de Souza - 2015) initial Cortex A15 version, based on Cortex A8 @ @ @ Redistribution and use in source and binary forms, with or without @ modification, are permitted provided that the following conditions @ are met: @ @ Redistributions of source code must retain the above copyright @ notice, this list of conditions and the following disclaimer. @ @ Redistributions in binary form must reproduce the above copyright @ notice, this list of conditions and the following disclaimer in the @ documentation and/or other materials provided with the @ distribution. @ @ Neither the name of Texas Instruments Incorporated nor the names of @ its contributors may be used to endorse or promote products derived @ from this software without specific prior written permission. @ @ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT @ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT @ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, @ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY @ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT @ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE @ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @ @****************************************************************************** @****************************** Global Symbols******************************* .global Entry .global __stack .global __bss_start__ .global __bss_end__ .global start_boot @************************ Internal Definitions ****************************** @ @ to set the mode bits in CPSR for different modes @ .set MODE_USR, 0x10 .set MODE_FIQ, 0x11 .set MODE_IRQ, 0x12 .set MODE_SVC, 0x13 .set MODE_ABT, 0x17 .set MODE_UND, 0x1B .set MODE_SYS, 0x1F .equ I_F_BIT, 0xC0 @**************************** Code Section *********************************** .text @ @ This code is assembled for ARM instructions @ .code 32 @****************************************************************************** @ @****************************************************************************** @ @ The reset handler sets up the stack pointers for all the modes. The FIQ and @ IRQ shall be disabled during this. Then clears the BSS section, enters the @ main function. Entry: @ @ The stack for all the modes (Abort, FIQ, etc.) is set by @ the runtime support library. @ @ @ Set up the Vector Base Address Regsiter @ LDR r0, = __isr_vector MCR p15, 0, r0, c12, c0, 0 @ Write VBAR Register .if __ARM_PCS_VFP == 1 @ @ Enable NEON extensions and the VFP. Must be done before entering user mode. @ MRC p15, #0, r3, c1, c0, #2 @ Read CPACR ORR r3, r3, #0x00F00000 @ Enable access to CP10 and CP11 MCR p15, #0, r3, c1, c0, #2 @ Write CPACR MOV r3, #0 MOV r0,#0x40000000 //FMXR FPEXC,r0 @ Set FPEXC bit 30 to enable VFP MCR p15, #0, r3, c7, c5, #4 @ flush prefetch buffer because of FMXR above .endif .if USERMODE == 1 @ @ Change to user mode. It allows for a stack smaller than 64kB. @ MSR cpsr_c, #MODE_USR|I_F_BIT @ change to user mode .endif @ @ The BSS section is cleared by the runtime support library @ @ @ Enter the main function. @ The symbol _start is the entry point for the runtime support library @ Enter_BootLoader: LDR r10, = _start @ Get the address of _start MOV lr,pc @ Dummy return BX r10 @ Branch to main SUB pc, pc, #0x08 @ looping @ @ Set the Stack space here @ .section .stack .align 4 .globl __StackBase .globl __StackLimit __StackLimit: @ .space 0x400 @ the stack size is set by the linker script .size __StackLimit, . - __StackLimit __StackBase: .size __StackBase, . - __StackBase @ @ Set the Heap space here @ .section .heap .align 4 .globl __HeapBase .globl __HeapLimit __HeapBase: @ .space 0x400 @ the heap size is set by the linker script .size __HeapBase, . - __HeapBase __HeapLimit: .size __HeapLimit, . - __HeapLimit @ @ Set the Interrupt vector table here @ .section .isr_vector .align 4 .globl __isr_vector __isr_vector: LDR pc, [pc,#24] @ 0x00 Reset LDR pc, [pc,#-8] @ 0x04 Undefined Instruction LDR pc, [pc,#24] @ 0x08 Supervisor Call LDR pc, [pc,#-8] @ 0x0C Prefetch Abort LDR pc, [pc,#-8] @ 0x10 Data Abort LDR pc, [pc,#-8] @ 0x14 Not used LDR pc, [pc,#-8] @ 0x18 IRQ interrupt LDR pc, [pc,#-8] @ 0x1C FIQ interrupt .long Entry .long 0 .long SVC_Handler .long 0 .long 0 .long 0 .long 0 .long 0 /* External interrupts */ .long Default_Handler .size __isr_vector, . - __isr_vector /* Macro to define default handlers. Default handler * will be weak symbol and just dead loops. They can be * overwritten by other handlers */ .macro def_default_handler handler_name .align 1 .thumb_func .type \handler_name, %function \handler_name : B . .size \handler_name, . - \handler_name .endm def_default_handler NMI_Handler def_default_handler HardFault_Handler def_default_handler SVC_Handler def_default_handler PendSV_Handler def_default_handler SysTick_Handler def_default_handler Default_Handler .weak DEF_IRQHandler .set DEF_IRQHandler, Default_Handler @ @ End of the file @ .end