IAR EWARM trouble wtih Stellaris ARM

I posted this on AVR freaks but I thought someone over here might know as well. Sorry to be “that guy”

I am trying to build a project for the Stellaris LM3S9B92 (EvalBot platform) with IAR EWARM 6.21.1.2846 and I don’t seem to be getting the settings right. I have followed every relevant instructions I can find and don’t see any differences between my set up and any of the example set ups.

Currently I’m getting a link error, or two rather but I’m guessing they are both arising from a single issue.

Error[Li005]: no definition for “__iar_program_start” [program entry]

Error[Li005]: no definition for “__iar_program_start” [referenced from C:\StellarisWare\boards\ek-lm3s9b92\bot_play\ewarm\Obj\startup_ewarm.o]

I have __iar_program_start defined as the entry symbol in my program just as the directions say. I only see that symbol used twice in any of the example projects. It’s defined in the start up file and then placed at the reset vector in the vector table. Here is TI’s startup_ewarm.c file

//*****************************************************************************
//
// startup_ewarm.c - Startup code for use with IAR's Embedded Workbench,
//                   version 5.
//
// Copyright (c) 2009-2011 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
// 
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
// 
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
// 
// This is part of revision 6852 of the EK-LM3S9B92 Firmware Package.
//
//*****************************************************************************

//*****************************************************************************
//
// Enable the IAR extensions for this source file.
//
//*****************************************************************************
#pragma language=extended

//*****************************************************************************
//
// Forward declaration of the default fault handlers.
//
//*****************************************************************************
static void NmiSR(void);
static void FaultISR(void);
static void IntDefaultHandler(void);

//*****************************************************************************
//
// The entry point for the application startup code.
//
//*****************************************************************************
extern void __iar_program_start(void);

//*****************************************************************************
//
// Reserve space for the system stack.
//
//*****************************************************************************
static unsigned long pulStack[64] @ ".noinit";

//*****************************************************************************
//
// A union that describes the entries of the vector table.  The union is needed
// since the first entry is the stack pointer and the remainder are function
// pointers.
//
//*****************************************************************************
typedef union
{
    void (*pfnHandler)(void);
    unsigned long ulPtr;
}
uVectorEntry;

//*****************************************************************************
//
// The vector table.  Note that the proper constructs must be placed on this to
// ensure that it ends up at physical address 0x0000.0000.
//
//*****************************************************************************
__root const uVectorEntry __vector_table[] @ ".intvec" =
{
    { .ulPtr = (unsigned long)pulStack + sizeof(pulStack) },
                                            // The initial stack pointer
    __iar_program_start,                    // The reset handler
    NmiSR,                                  // The NMI handler
    FaultISR,                               // The hard fault handler
    IntDefaultHandler,                      // The MPU fault handler
    IntDefaultHandler,                      // The bus fault handler
    IntDefaultHandler,                      // The usage fault handler
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    IntDefaultHandler,                      // SVCall handler
    IntDefaultHandler,                      // Debug monitor handler
    0,                                      // Reserved
    IntDefaultHandler,                      // The PendSV handler
    IntDefaultHandler,                      // The SysTick handler
    IntDefaultHandler,                      // GPIO Port A
    IntDefaultHandler,                      // GPIO Port B
    IntDefaultHandler,                      // GPIO Port C
    IntDefaultHandler,                      // GPIO Port D
    IntDefaultHandler,                      // GPIO Port E
    IntDefaultHandler,                      // UART0 Rx and Tx
    IntDefaultHandler,                      // UART1 Rx and Tx
    IntDefaultHandler,                      // SSI0 Rx and Tx
    IntDefaultHandler,                      // I2C0 Master and Slave
    IntDefaultHandler,                      // PWM Fault
    IntDefaultHandler,                      // PWM Generator 0
    IntDefaultHandler,                      // PWM Generator 1
    IntDefaultHandler,                      // PWM Generator 2
    IntDefaultHandler,                      // Quadrature Encoder 0
    IntDefaultHandler,                      // ADC Sequence 0
    IntDefaultHandler,                      // ADC Sequence 1
    IntDefaultHandler,                      // ADC Sequence 2
    IntDefaultHandler,                      // ADC Sequence 3
    IntDefaultHandler,                      // Watchdog timer
    IntDefaultHandler,                      // Timer 0 subtimer A
    IntDefaultHandler,                      // Timer 0 subtimer B
    IntDefaultHandler,                      // Timer 1 subtimer A
    IntDefaultHandler,                      // Timer 1 subtimer B
    IntDefaultHandler,                      // Timer 2 subtimer A
    IntDefaultHandler,                      // Timer 2 subtimer B
    IntDefaultHandler,                      // Analog Comparator 0
    IntDefaultHandler,                      // Analog Comparator 1
    IntDefaultHandler,                      // Analog Comparator 2
    IntDefaultHandler,                      // System Control (PLL, OSC, BO)
    IntDefaultHandler,                      // FLASH Control
    IntDefaultHandler,                      // GPIO Port F
    IntDefaultHandler,                      // GPIO Port G
    IntDefaultHandler,                      // GPIO Port H
    IntDefaultHandler,                      // UART2 Rx and Tx
    IntDefaultHandler,                      // SSI1 Rx and Tx
    IntDefaultHandler,                      // Timer 3 subtimer A
    IntDefaultHandler,                      // Timer 3 subtimer B
    IntDefaultHandler,                      // I2C1 Master and Slave
    IntDefaultHandler,                      // Quadrature Encoder 1
    IntDefaultHandler,                      // CAN0
    IntDefaultHandler,                      // CAN1
    IntDefaultHandler,                      // CAN2
    IntDefaultHandler,                      // Ethernet
    IntDefaultHandler,                      // Hibernate
    IntDefaultHandler,                      // USB0
    IntDefaultHandler,                      // PWM Generator 3
    IntDefaultHandler,                      // uDMA Software Transfer
    IntDefaultHandler,                      // uDMA Error
    IntDefaultHandler,                      // ADC1 Sequence 0
    IntDefaultHandler,                      // ADC1 Sequence 1
    IntDefaultHandler,                      // ADC1 Sequence 2
    IntDefaultHandler,                      // ADC1 Sequence 3
    IntDefaultHandler,                      // I2S0
    IntDefaultHandler,                      // External Bus Interface 0
    IntDefaultHandler                       // GPIO Port J
};

//*****************************************************************************
//
// This is the code that gets called when the processor receives a NMI.  This
// simply enters an infinite loop, preserving the system state for examination
// by a debugger.
//
//*****************************************************************************
static void
NmiSR(void)
{
    //
    // Enter an infinite loop.
    //
    while(1)
    {
    }
}

//*****************************************************************************
//
// This is the code that gets called when the processor receives a fault
// interrupt.  This simply enters an infinite loop, preserving the system state
// for examination by a debugger.
//
//*****************************************************************************
static void
FaultISR(void)
{
    //
    // Enter an infinite loop.
    //
    while(1)
    {
    }
}

//*****************************************************************************
//
// This is the code that gets called when the processor receives an unexpected
// interrupt.  This simply enters an infinite loop, preserving the system state
// for examination by a debugger.
//
//*****************************************************************************
static void
IntDefaultHandler(void)
{
    //
    // Go into an infinite loop.
    //
    while(1)
    {
    }
}

I have searched and searched and searched and I don’t see __iar_program_start used anywhere else in any of the 20+ example projects. Google doesn’t reveal much either. It’s like the example programs just automagically jump to main from __iar_program_start.

When I used to play with GCC and the AT91SAM7 chips you would see something like

void __iar_program_start()
{
     low_level_init();
     main();
}

but I don’t see anything like that in any of the working examples. Just on a slightly educated hunch I renamed my main function from main() to __iar_program_start and I was successfully able to build and load code onto my hardware. The debugger complained when it couldn’t find main but I told it to shut up and it jumped right to __iar_program_start and then let me single step through the code. I turned some LED’s on just to make sure it was in fact running.

Please help!

For the NXP ARMs, probably same for Stellaris, IAR has two programs of note that the linker builds in by default

__iar_program_start

is in IAR’s generic assembly language code in their libraries. It gets the reset vectored jump. It does basic setup of the CPU modes and stack pointers. It then (on mine) goes to “low level init” which uses linker created values to initialize the BSS and zero static storage areas, etc. That then jumps to your main().

So it looks like your project eww and all isn’t correct.

The way a beginner can get this right is to just take one of IAR’s demo programs, or one from Stellaris with an IAR tool set suite of files, then edit main.c to contain your code as you learn. You’ll also need to use the IDE to alter settings in the project tabs of the IDE, for things like stack size, and so on. The key is to start with a working demo program for the IAR.

That definitely clears some things up. Any clue what I am missing that would cause these two pieces of code not to be built? I started with example projects and putting my own code in their main function but I am to the point now where I want to learn to do it from scratch. Much of this stuff is indistinguishable from magic when you just blindly throw your code into main. I want to understand the stuff like __low_level_init & __iar_program_start.

Thank you

I had checked the project settings at least a dozen times over and couldn’t find anything but I definitely missed something. It wasn’t until I examined the arguments passed into the linker that I noticed it. Under general options - library configuration I had the drop down set to custom instead of normal. That resulted in “–no_library_search” being passed into the linker. I knew that wasn’t right. It took me two days to find that but it finally works now. Thank you.

Right. That lost 2 days is why I suggested that as a new user, it’s best to modify an existing full project as your first effort.

I already explained to you why I didn’t want to do that. This wasn’t my first effort. I’ve been blindly throwing code in someone else’s main since March. It was a hurdle I would have to jump regardless of how long I avoided it. I didn’t “lose” 2 days… I gained 2 days… of experience.