Jump to content

    

Сборка и настройка GCC кросс-компилятора под MIPS

Привет всем,

 

с некоторых пор я начас своё знакомство с SoftCore "Plasma" (MIPS1) и сваял для Altera DE1 небольшой тестовый проект, который включает в себя собственно сам процессор, UART, 2 таймера, SD-Card по SPI и кнопки/светодиоды. Память - 8мб SDRAM. Процессор тикает на частоте 12.85МГц, память на 90МГц. Пока нет никакого кэша.

Раньше я использовал сборку GCC от Steve Rhoads. Но эта сборка не имеет никаких библиотек, поэтому всё приходилось писать самому.

Поэтому я решил собрать GCC + Newlib.

Собирал под Win32 (MinGW).

  • Binutils 2.22
  • GCC 4.6.2
  • Newlib 1.20
  • GDB 7.4

Кое как получилось собрать :biggrin: Даже вроде заработало, но только проблемы с printf.

Вот мой start-up code:

   .text
   .align 2
   .global _start
   .ent    _start

_start:
   .set noreorder

   la    $gp, _gp             #initialize global pointer
   la    $5, __bss_start      #$5 = .sbss_start
   la    $4, _end             #$2 = .bss_end
   la    $sp, 0x7FFFF         #initialize stack pointer

$BSS_CLEAR:
   sw    $0, 0($5)
   slt   $3, $5, $4
   bnez  $3, $BSS_CLEAR
   addiu $5, $5, 4


   jal main
   nop

loop:
   j loop
   .set reorder
   .end _start

 

Скрипт LD:

ENTRY(_start)

SECTIONS
{
   . = 0x00000000;
   .text :
   {
      boot.o (.text)
      *(.text)
   }
   .data : { *(.data) }

   _gp = . + 0x7ff0;
   __bss_start = .;

   .bss : { *(.bss) }

   _end = .;
}

 

Syscalls:

#include <sys/stat.h>

#define _MR(A) (*(volatile unsigned int*)(A))
#define _MW(A,V) *(volatile unsigned int*)(A)=(V)

int fstat(int file, struct stat *st)
{
   st->st_mode = S_IFCHR;
   return 0;
}

int read(int file, char *ptr, int len)
{
   return 0;
}

int lseek(int file, int ptr, int dir)
{
   return 0;
}

int isatty(int file)
{
   return 1;
}

int close(int file)
{
   return -1;
}

int write(int file, char *ptr, int len)
{
   int todo;
   for (todo = 0; todo < len; todo++)
   {
      while(_MR(0x80000030)); // UART busy???
      _MW(0x80000020, *ptr++); // write to UART
   }
   return len;
}

caddr_t sbrk(int incr)
{
   extern char _end; /* Defined by the linker */
   static char *heap_end;
   char *prev_heap_end;
   if (heap_end == 0)
   {
      heap_end = &_end;
   }
   prev_heap_end = heap_end;
   heap_end += incr;
   return (caddr_t) prev_heap_end;
}

 

Программа:

#include <stdio.h>

int main(void)
{
   write(NULL,fff,3);
   printf("Hallo\n");
   while(1);
}

 

Прямой вызов write работает как надо, а вот printf нет.

Скорее всего, я думаю, у меня проблемы с heap/stack но так как опыта почти нет (всегда пользовался готовыми скриптами и start-up) то я завис. Почитал всё что смог найти в инете, но дальше дело не двигается.

Надеюсь на помощь знающих!

 

С уважением

Дима

Share this post


Link to post
Share on other sites
....

Поэтому я решил собрать GCC + Newlib.

....

Прямой вызов write работает как надо, а вот printf нет.

Предположение #1:

printf сначала выводит даные во временный буфер, и только потом когда он наполнится вызавает соответствующий write. Этот функционал можно отключить.

setvbuf(stdin, NULL, _IONBF, 0);

.....

Скорее всего, я думаю, у меня проблемы с heap/stack но так как опыта почти нет (всегда пользовался готовыми скриптами и start-up) то я завис.

.....

Тоже может быть.

Советую вопросы по newlib задавать в соответствующем разделе форума (http://electronix.ru/forum/index.php?showforum=162) т.к. Ваш вопрос по бОльшей части к MIPS не относится.

Share this post


Link to post
Share on other sites

А разве имена функций в syscalls не должны начинаться с нижнего подчеркивания ?

int _write(int file, char *ptr, int len)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this