Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12599 Discussions

undefined reference to 'main'

Altera_Forum
Honored Contributor II
3,295 Views

Hi Guys, 

I have only just started with the NIOS II and associated tools so I accept I could have done a million things wrong, but: 

 

I have tried creating a simple application that contains a UART module, NIOS II/e and on chip RAM. 

 

I build the BSP without any problems (although it does seem to add drivers from a previous tutorial I did), i then create the application and point to the newly created BSP. I add the main.c source file which is listed below: 

 

# include <stdint.h> 

# include "system.h" 

 

int main(void) 

volatile uint32_t *uart = (volatile uint32_t*) UART_BASE; 

char *str = "Hello from NIOS II\n"; 

 

while (1) 

char *ptr = str; 

while (*ptr != '\0') 

while ((uart[2] & (1<<6)) == 0); 

uart[1] = *ptr; 

ptr++; 

 

return 0; 

 

but when i compile I get 2 errors: 

 

make:***[simpleNIOS2.elf] Error 1 

undefined reference to 'main' 

 

the first appears in my application file and the second in the alt_main.c file within the BSP. 

 

Can anyone point out where I might have gone wrong? 

many thanks 

David
0 Kudos
9 Replies
Altera_Forum
Honored Contributor II
1,774 Views

Does your main.c actually get compiled? 

(force a compilation error if necessary!) 

If not, you've failed to add it to the project properly. 

 

Also, unless your system doesn't have a data cache, the accesses to uart[] will be cached - not what you want.
0 Kudos
Altera_Forum
Honored Contributor II
1,774 Views

Hey DSL, thanks for the response. 

 

Not sure what you mean by having a data cache for the UART? Is tis something I need to add-in on the UART config pages in Qsys? 

 

but some further information on my problem. 

 

I created a new NIOS system (without UART!) that just uses the PIO module. I opened the SBT under 'run as adminsistrator' as there has been some reports about 'make' generating errors when it dosent have admin rights in Windows 7. Which in itself is a bit rubbish because if you permanently set the SBT to use admin rights, Quartus crashes when trying to open it!), so it has to be run from start menu->all programs, then run as admin!!! 

 

so, i get into SBT, i create a bsp, i create an application and the same problem as before happens 

 

if i use 'create application and bsp from template' and select hello world template, it works!  

However if I select the blank project instead of hello world, and add a source file to this it does not work and I get the same errors. 

I am confused as hell! 

D
0 Kudos
Altera_Forum
Honored Contributor II
1,774 Views

As dsl said, check that your file is compiled. You can write an obvious error in the code and see if it's picked up by the compiler.

0 Kudos
Altera_Forum
Honored Contributor II
1,774 Views

Hello folks, 

OK, i did that and yes, you were correct it hadn't compiled. So, i started playing around and I found out why (and Yes it was through my own stupidity!). 

 

I created a BSP, (and told it to ignore c++, reduce driver sizes etc) and then regenerated/cleaned/rebuilt. Then I added the new application, and added my main.c file. Then i added my code to this and clicked 'SAVE ALL'. it then compiled and built and downloaded into the FPGA and worked! 

DOH! Just missed the save. 

 

The reason that I missed this is because I also use a version of Eclipse that is streamlined for NXP processors the LPCxpresso edition supplied by CodeRed and I have never needed to hit save after putting in new files, i only ever needed to re-build. 

 

So thank you for your help! It really is people taking an interest that pushes us newbies along! 

 

DSL, i will look at the cache-ing you mentioned in relation to the UART as I wouldn't want to get caught out again. 

D
0 Kudos
Altera_Forum
Honored Contributor II
1,774 Views

The data cache he was talking about is on the CPU, not on the UART. If you have a data cache on the CPU, your instructions that attempt to write to the UART could end up writing only to the cache instead. This is why it is usually recommended to use the IORD/IOWR macros to access devices rather than pointers. 

In your case it shouldn't be a problem as you are using a Nios II/e, which doesn't have data cache IIRC, but you should keep it in mind if you plan to use a bigger Nios II CPU one day. 

I still think you should get now the good habit of using IORD/IORW though ;)
0 Kudos
Altera_Forum
Honored Contributor II
1,774 Views

Hi Daixiwen, 

It's funny you should mention using the macros, becuase I have just been trying to sort out how to write to the PIO ports I set up and was playing with pointers!! The only downside to the macros is that the names are a bit large and I may re-write the defines to be a little shorter and easier on the typing! 

 

One question ergarding the macros: 

 

If in my CPU i make a PIO port that is out only, are the read and direction registers still in the address map when I generate the BSP? If so are the registers that would have followed the read and direction registers shunted further up the address map? 

 

I would assume that they are always there regardless of whether they are implemented or not otherwise if the CPU was to change to include a read register and a new BSP generated all sorts of hell could break loose in the existing code! 

 

I hope my question makes sense! 

 

thank you once again! 

D
0 Kudos
Altera_Forum
Honored Contributor II
1,774 Views

My preference (like most software people who write device drivers) is to use C structures to map device registers. It is generally much less error-prone than using constants for all the offsets. 

 

I also like defined constant addresses for IO. Any software is likely to be written on completely different systems, and by different people than those writing the vhdl - so you don't want the addresses changing on the whim of some tool. 

 

On a Nios (without mmu, but with data cache) there are are two ways of bypassing the data cache: 

1) Use the 'stio' and 'stio' forms of the instructions. 

2) Set the msb of the physical address. 

Those Altera# defines with long names do the former, and might be multiplying offsets by 4 for good measure! 

 

We just cross compiler our code using gcc and make (etc) with our own carefully crafted linker script to put each section at the correct addresses.
0 Kudos
Altera_Forum
Honored Contributor II
1,774 Views

On the Altera PIO the read, write and direction registers are always at the same place, and it doesnæt depend on the hardware configuration. So you should always find your registers at the same offsets.

0 Kudos
Altera_Forum
Honored Contributor II
1,774 Views

Thanks Guys, 

I am now going to get stuck into writing my structs to map the device registers (as that is what I am used to from my LPC cortex M3 programming). I have to say the NIOS II system is really useful (although the learning curve is a bit steep to start with), but the potential is awesome. Especially when you consider all the third party IP there is out there! 

 

Again Thank You, and I'm sure I'll soon have more questions! ;-)
0 Kudos
Reply