Страница 1 из 1

Плата с ARM CPU и Линух (Решено)

СообщениеДобавлено: 08.09.2013 14:34:36
mig-31
Добрый день.
Никак не могу найти ошибку из-за которой процессор зависает при записи в регистры PIOC.
Плата Portux G20 http://www.taskit.de/en/products/portuxg20/index.htm с Atmel AT91SAM9G20 с Angstrom Linux.
У этого процессора есть три линии конфигурируемых input/output линий по 32 на каждой линии PIOA, PIOB и PIOC.
Сдвиг на PIOB =$FFFFF600, PIOC=$FFFFF800. Сдвиг на регистры конфигурации
PER= $0000 //enable registr
OER=$0010 //enable output registr
IFDR=$0024 //enable filtr registr
SODR=$0030 //set ouput register - set high on output
CODR=$0034 //clear output registr - set low on output
IDR=$0044 //disable interrupt registr
Все регистры 32-х битные.

При записи в регистры линии PIOC процессор зависает.
Пример кода на С работает без проблем.

Мой код на Паскале
Код: Выделить всё
program project1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, SysUtils,BaseUnix,crt,errors
  { you can add units after this };
const
  //map consts
  MAP_SIZE=4096;
  MAP_MASK=(MAP_SIZE-1);
  //BASE ADDRESS OF PIOB and PIOC
  //calculating address due of page size 4096 = $1000 PIOB_BASE= $FFFFF600 div $1000 =$FFFFF
  //calculating address due of page size 4096 = $1000 PIOB_BASE= $FFFFF800 div $1000 =$FFFFF
  //page number offset
  PIO_BASE=$FFFFF;
  //OFFSET TO CONTROL REGISTERS REGISTERS address  PIOB
  PIOB_OFFSET=$600;
  PIOB_PER=(PIOB_OFFSET+$0000);
  PIOB_OER=(PIOB_OFFSET+$0010);
  PIOB_IFDR=(PIOB_OFFSET+$0024);
  PIOB_SODR=(PIOB_OFFSET+$0030);
  PIOB_CODR=(PIOB_OFFSET+$0034);
  PIOB_IDR=(PIOB_OFFSET+$0044);

  //OFFSET TO CONTROL REGISTERS REGISTERS address  PIOB
  PIOC_OFFSET=$600;
  PIOC_PER=(PIOC_OFFSET+$0000);
  PIOC_OER=(PIOC_OFFSET+$0010);
  PIOC_IFDR=(PIOC_OFFSET+$0024);
  PIOC_SODR=(PIOC_OFFSET+$0030);
  PIOC_CODR=(PIOC_OFFSET+$0034);
  PIOC_IDR=(PIOC_OFFSET+$0044);
  //set 1 on 27 pin on PIOB controller registers
  PIOB_B27=(1 shl 27);
  //set 1 on pin 0 on PIOC controller registers
  PIOC_C00=(1 shl 0);
  blink_count=5;

var
  fd:cint;
  mem_base:^Longword;
  reg_addr:^Longword;
  i:byte;
begin
  //get file descriptor
  fd:=fpOpen('/dev/mem',O_RdWr or O_SYNC);
  if fd<0 then begin
    writeln('Cant get file description');
    Halt(1);
  end;
  writeln('/dev/mem has opened');
  //map 1 page memory 4kB
  //fpmmap is used page OFFSET not byte
  mem_base:=fpmmap(Nil,MAP_SIZE,PROT_READ or PROT_WRITE,MAP_SHARED ,fd, PIO_BASE);
  if ptrint(mem_base)=-1 then begin
    writeln('Memory map error. Error: ',strerror(fpGeterrno));
    Halt(2);
  end;
  writeln('Memory mapped on address $',hexstr(mem_base));
 
  //работает
  // setting registers to blink on pin B29
  //enable registr
  reg_addr:=Pointer(Longword(mem_base)+PIOB_PER);
  reg_addr^:=PIOB_B27;
  //disable input filtr
  reg_addr:=Pointer(Longword(mem_base)+PIOB_IFDR);
  reg_addr^:=PIOB_B27;
  //disable interrupt
  reg_addr:=Pointer(Longword(mem_base)+PIOB_IDR);
  reg_addr^:=PIOB_B27;
  //enable output
  reg_addr:=Pointer(Longword(mem_base)+PIOB_OER);
  reg_addr^:=PIOB_B27;
  //blinking
  for i:=0 to blink_count do begin
    //set output data register
    reg_addr:=Pointer(Longword(mem_base)+PIOB_SODR);
    reg_addr^:=PIOB_B27;
    sleep(1000);
    //clear output data register
    reg_addr:=Pointer(Longword(mem_base)+PIOB_CODR);
    reg_addr^:=PIOB_B27;
    sleep(1000);
  end;

  //вешает процессор
  // setting registers to blink on pin C00
  //enable registr
  reg_addr:=Pointer(Longword(mem_base)+PIOC_PER);
  reg_addr^:=PIOC_C00;
  //disable input filtr
  reg_addr:=Pointer(Longword(mem_base)+PIOC_IFDR);
  reg_addr^:=PIOC_C00;
  //disable interrupt
  reg_addr:=Pointer(Longword(mem_base)+PIOC_IDR);
  reg_addr^:=PIOC_C00;
  //enable output
  reg_addr:=Pointer(Longword(mem_base)+PIOC_OER);
  reg_addr^:=PIOC_C00;
  //blinking
  for i:=0 to blink_count do begin
    //set output data register
    reg_addr:=Pointer(Longword(mem_base)+PIOC_SODR);
    reg_addr^:=PIOC_C00;
    sleep(1000);
    //clear output data register
    reg_addr:=Pointer(Longword(mem_base)+PIOC_CODR);
    reg_addr^:=PIOC_C00;
    sleep(1000);
  end;
//close file descriptor
fpClose(fd);
//unmap memory
if fpMUnMap(mem_base, map_size)<>0 then Halt(fpgeterrno);
end.


Код на С
Код: Выделить всё
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>
 
#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)

#define PIOB_BASE 0xfffff600UL
#define PIOC_BASE 0xfffff800UL

#define PIO_C00 ((unsigned long) 1 << 0)
#define PIO_C01   ((unsigned long) 1 << 1)
#define PIO_B27   ((unsigned long) 1 << 27)

#define PIOB_PER PIOB_BASE + 0x0000
#define PIOB_OER PIOB_BASE + 0x0010
#define PIOB_IFDR PIOB_BASE + 0x0024
#define PIOB_SODR PIOB_BASE + 0x0030
#define PIOB_CODR PIOB_BASE + 0x0034
#define PIOB_IDR PIOB_BASE + 0x0044


#define PIOC_PER PIOC_BASE + 0x0000
#define PIOC_OER PIOC_BASE + 0x0010
#define PIOC_IFDR PIOC_BASE + 0x0024
#define PIOC_SODR PIOC_BASE + 0x0030
#define PIOC_CODR PIOC_BASE + 0x0034
#define PIOC_IDR PIOC_BASE + 0x0044

int main(int argc, char **argv) {
    int fd, i, repetitions;
    void *map_base;
    if (argc > 1)
    {
       repetitions =(atoi(argv[1]));
    }
    else
    {
       printf("\nMissing argument\n");
         printf("Usage: led REPETITIONS\n");
    printf("REPETITIONS: int, that specifies number of repetitions of blinking led cycles\n\n\n");
         exit(1);
    }   


    if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1)
    {
       printf("Couldn't open /dev/mem.\n");
   exit(1);
    }
    printf("/dev/mem opened.\n");
    fflush(stdout);
   
    /* Map one page */
    map_base = mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PIOB_BASE  & ~MAP_MASK);
    if(map_base == (void *) -1)
    {
       printf("Couldn't get Map-Address.\n");
      exit(1);
   }
    printf("Memory mapped shift %p.\n", PIOB_BASE  & ~MAP_MASK);
    printf("Memory mapped at address %p.\n", map_base);
    fflush(stdout);
   
    // Configure the registers

    *((unsigned long *) (map_base + (PIOB_PER & MAP_MASK))) = PIO_B27; //enable io
    printf("Memory shift to PER %p.\n", PIOB_PER & MAP_MASK);
    *((unsigned long *) (map_base + (PIOB_IFDR & MAP_MASK))) = PIO_B27; //disable input filter
     printf("Memory shift to IFDR %p.\n", PIOB_IFDR & MAP_MASK);
    *((unsigned long *) (map_base + (PIOB_IDR & MAP_MASK))) = PIO_B27;  // disable interrupt
    *((unsigned long *) (map_base + (PIOB_OER & MAP_MASK))) = PIO_B27;  // Enable output

    *((unsigned long *) (map_base + (PIOC_PER & MAP_MASK))) = PIO_C00 | PIO_C01;
    *((unsigned long *) (map_base + (PIOC_IFDR & MAP_MASK))) = PIO_C00 | PIO_C01;
    *((unsigned long *) (map_base + (PIOC_IDR & MAP_MASK))) = PIO_C00 | PIO_C01;
    *((unsigned long *) (map_base + (PIOC_OER & MAP_MASK))) = PIO_C00 | PIO_C01;

    i = 0;
    while(i < repetitions)
    {         
      *((unsigned long *) (map_base + (PIOC_CODR & MAP_MASK))) = PIO_C00;
      *((unsigned long *) (map_base + (PIOB_SODR & MAP_MASK))) = PIO_B27;
      sleep(1);
      *((unsigned long *) (map_base + (PIOB_CODR & MAP_MASK))) = PIO_B27; 
      *((unsigned long *) (map_base + (PIOC_SODR & MAP_MASK))) = PIO_C01;
      sleep(1);
      *((unsigned long *) (map_base + (PIOC_CODR & MAP_MASK))) = PIO_C01;
      *((unsigned long *) (map_base + (PIOC_SODR & MAP_MASK))) = PIO_C00;      
      sleep(1);
      i++;
    }
    *((unsigned long *) (map_base + (PIOB_CODR & MAP_MASK))) = PIO_B27; 
    *((unsigned long *) (map_base + (PIOC_CODR & MAP_MASK))) = PIO_C00 | PIO_C01;      
    if(munmap(map_base, MAP_SIZE) == -1) exit(1);
    close(fd);
    return 0;
}


Код на Паскале компилировал на Магея Линух 3 64-бит с crossarm и fpc юнитами 2.5.1 для ARM и прямо на плате fpc 2.6.2. Результат один и тот же при записи в регистры PIOC процессор зависает. Чтение регистра возвращающего состояние (OFFSET= $0008) outputa выполняется без проблем.
Уже не зная, где искать ошибку. Может баг функции fpmmap - выделяет 512 байт вместо 4 килобайт (хотя наверно это невозможно)?

Спасибо за любую идею.

Re: Плата с ARM CPU и Линух

СообщениеДобавлено: 10.09.2013 14:54:02
mig-31
Решено. Ошибка была в записи используемого бита.

Re: Плата с ARM CPU и Линух (Решено)

СообщениеДобавлено: 10.09.2013 15:16:33
vada
Стесняюсь спросить, сколько девайс стоит? А то вот тут http://www.zao-zeo.ru/ наши продают похожие устройства за какие-то нереальные деньги.

Re: Плата с ARM CPU и Линух (Решено)

СообщениеДобавлено: 10.09.2013 15:58:01
debi12345
за какие-то нереальные деньги

Ну, для начала - чипы от MARWELL (распаиваемые на этих платах) всегда были недешевые.

Re: Плата с ARM CPU и Линух (Решено)

СообщениеДобавлено: 10.09.2013 16:17:45
vada
чипы от MARWELL (распаиваемые на этих платах) всегда были недешевые.

И что? Старушка у метро говорила что она выкопала 8 ведер картошки.

Re: Плата с ARM CPU и Линух (Решено)

СообщениеДобавлено: 10.09.2013 16:32:53
Sergei I. Gorelkin
Дык, на taskit.de есть магазин с ценами... и я бы не сказал, что у наших цены по сравнению с ними прямо-таки нереальные.

Re: Плата с ARM CPU и Линух (Решено)

СообщениеДобавлено: 10.09.2013 16:41:57
debi12345
и я бы не сказал, что у наших цены по сравнению с ними прямо-таки нереальные.

Цены на промэлектронику всегда завышены (если гос-во это не берет на конроль) - фирмачи считают, что у целого предприятия на несчатную плату несколько сотен басов всегда найдутся :) Подход конечно идиотский и недальновидный - затруднящий техническое творчество индивидуалов на дому, в кружкАх,.

Re: Плата с ARM CPU и Линух (Решено)

СообщениеДобавлено: 11.09.2013 09:34:30
mig-31
На сайте есть ценник PriceList

Re: Плата с ARM CPU и Линух (Решено)

СообщениеДобавлено: 11.09.2013 10:39:00
vada
Дауж. Ценник кусается. Проще купить PocketBook какой-нибудь.

Re: Плата с ARM CPU и Линух (Решено)

СообщениеДобавлено: 11.09.2013 13:44:51
mig-31
Не сказал бы. Главное применение, наверно автоматизация, вместо PLC (некоторые PLC выполняют только один Task ). Цена ниже, цены PLC с подобным количеством входов/выходов. Но PLC проще программировать.

Re: Плата с ARM CPU и Линух (Решено)

СообщениеДобавлено: 11.09.2013 15:08:49
debi12345
Данные девайсы вообще не расчитаны на их програмирование. Их плюс - на их можно использовать море уже имеющегося линуксового софта - например ZoneMinder для систем видеонаблюдения. И даже выневого софта :)

Re: Плата с ARM CPU и Линух (Решено)

СообщениеДобавлено: 11.09.2013 17:37:53
mig-31
Подобная плата

http://www.acmesystems.it/FOXG20

Re: Плата с ARM CPU и Линух (Решено)

СообщениеДобавлено: 11.09.2013 17:43:49
debi12345
http://www.acmesystems.it/FOXG20

Оно умеет писАть на внешний USB-HDD ? (чтобы не убивать загрузочную MicroSD)

Re: Плата с ARM CPU и Линух (Решено)

СообщениеДобавлено: 11.09.2013 21:14:59
mig-31
debi12345 писал(а):Оно умеет писАть на внешний USB-HDD ?


Обе платы работают с USB-HDD, но наверно потребуется внешнее питание.