Никак не могу найти ошибку из-за которой процессор зависает при записи в регистры 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 килобайт (хотя наверно это невозможно)?
Спасибо за любую идею.






 Подход конечно идиотский и недальновидный - затруднящий техническое творчество индивидуалов на дому, в кружкАх,.
 Подход конечно идиотский и недальновидный - затруднящий техническое творчество индивидуалов на дому, в кружкАх,.