Homepage Wiki Forum Buy

GNUBLIN embedded GNU/Linux

Open source learning and training plattorm for embedded GNU / Linux
A projects from Hochschule Augsburg and embedded projects GmbH

Project homepage: http://www.gnublin.org
Wiki: http://wiki.gnublin.org
Aktuelle Zeit: Mo 16. Jul 2018, 03:03

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]




Ein neues Thema erstellen Auf das Thema antworten  [ 10 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Gunblin Lan: Fragen zu IO und Timer
BeitragVerfasst: Mo 17. Nov 2014, 21:57 
Offline

Registriert: Mo 7. Okt 2013, 08:00
Beiträge: 36
Hallo

ich habe einige Fragen zum Gnublin LAN
a) Kann man Pin 7,8,10 (SPI Interface) als GPIO-Pins für eigene Applikationen nutzen ? Oder hängt der Ethernetchip auch an diesen. Das geht nicht direkt aus dem Schaltplan hervor - die Labels der SPI-Pins haben unterschiedliche Namen. Vermutlich heisst das aber nicht, dass sie nicht trotzdem miteinander verbunden sind.
b) Kann einer der Pins am am Gnublin Connector als Flankentrigger, der mit einem der Timer verbunden ist, konfiguriert werden ? Ich würde gerne eine Umdrehungszahl/Zeiteinheit an einer angetriebenen Achse messen.
c) Kann man den Gnublin in einen Low-Power-Sleep Modus versetzen, und durch einen Timer nach einer bestimmten Zeit wieder aufwecken ?

Vielen Dank

Tilman


Nach oben
 Profil  
 
BeitragVerfasst: Di 18. Nov 2014, 00:44 
Offline

Registriert: Di 26. Jun 2012, 10:27
Beiträge: 172
Zu A)
Der Ethernetchip ist per SPI mit dem Gnublin Verbunden. Man kann mehrere Chips an einem SPI-Interface anschließen, nur braucht man für jedes eine separate Selectleitung. Standardmäßig sind glaube ich nur zwei definiert, einen für den Ethernetchip und eine geht an den Gnublin Conector. Für mehr muss man den Treiber anpassen. (make menuconfig beim Kernel)
Nur wenn man kein SPI benutzt lassen sich die Pins auch als GPIO nutzen.

Zu B)
Der LPC hat mehre Timer, zwei (kann auch sein das es nur einer ist) benutzt Linux für die Echtzeituhr und dem Taskscheduler.
Wenn noch einer frei ist, kannst du ein Kernelmodul schreiben und ihn verwenden. Ob der einen Clockeingang hat und dieser auch herausgeführt ist must du mal nachschauen, die meisten GPIOs vom LPC sind nicht bedrahtet.

Ansonsten musst du die Flanken selbst zählen. Die GPIOs haben auch Flankenregister, aus einem User-Programm kannst du sie aber nur Pollen.
Mit einem Kernel-Modul kannst du eine ISR dafür schreiben.

Zu C)
Damit habe ich mich nicht beschäftigt. Der LPC selbst sollte sowas können, nur unterstützt das Linux nicht.
Ein Suspend to Ram oder Suspend to Disk, wie beim PC wird es wohl nicht geben.
Ob sich die CPU beim nichts tun, so wie bei einem x86, teilweise abschaltet kann ich auch nicht sagen.


Nach oben
 Profil  
 
BeitragVerfasst: Mi 19. Nov 2014, 00:32 
Offline

Registriert: Mo 7. Okt 2013, 08:00
Beiträge: 36
Hallo

zum Suspend habe ich hier etwas gefunden:

http://embeddedfreak.wordpress.com/2010 ... on-ea3131/

Ausprobiert habe ich es nicht, da beim gnublin-Lan der Pin mI2STX_BCK0 defnitiv nicht verbunden ist. Cat /sys/power/state enthält jedenfalls beide Modi.

Mal den Kernel-Source herunterladen, Vielleicht läßt sich die IRQ-Quelle ändern.

Gruß
Tilman


Nach oben
 Profil  
 
BeitragVerfasst: Mi 19. Nov 2014, 09:40 
Offline

Registriert: Di 26. Jun 2012, 10:27
Beiträge: 172
Suspend to Ram doch möglich, aber wie wacht man auf?
"The default kernel is configured with wake up source from SD-Card card detect IRQ (mI2STX_BCK0). Hence, the system can only be waken up by inserting or removing SD-Card into EA3131 SD-Card slot."


Mit dem Bereich habe ich mich noch nicht beschäftigt, aber man kann sicherlich andere Signale zum Aufwachen konfigurieren. Interne Interrupts (Timer) oder Externe.
Der ENC28J60 kann WoL und sendet ein Interrupt wenn er "Magic Paket" an seiner Mac-Adresse empfängt (Sowohl auf dem INT und WOL Pin des Chips soviel ich weiß; WOL Pin ist nicht bedrahtet).


Nach oben
 Profil  
 
BeitragVerfasst: Mi 19. Nov 2014, 16:18 
Offline

Registriert: Mo 7. Okt 2013, 08:00
Beiträge: 36
Hallo

Es gibt 2 Modi: Standyby und Suspend to RAM. Im Datenblatt gibt es die Section 6.19, die den Event-Router beschreibt. Damit kann man den Prozessor wieder aufwecken -- entweder über eine externe Leitung, oder aber über ein Signal aus der CGU (Clock Generation Unit).
Wie aber programmiert man diese ?


https://github.com/embeddedprojects/gnublin-lpc3131-2.6.33/blob/master/linux-2.6.33-lpc313x/arch/arm/mach-lpc313x/pm.c
Zitat:
* STANDBY mode has *all* drivers suspended; ignores irqs not
* marked as 'wakeup' event sources; and reduces DRAM power.
* System can be woken-up by internal events. The internal
* blocks which are set to wake should have their clocks
* running without WAK_EN bit set in CGU.

Zitat:
* Suspend-to-RAM is like STANDBY plus slow clock mode, so
* drivers must suspend more deeply: only the base domains
* switches SYS_BABSE, APB0, APB1 are clocked using the
* main oscillator. The system can be woken-up by EXTERNAL
* events ONLY. Ie., external interrupts handles through
* event router.


Nach oben
 Profil  
 
BeitragVerfasst: Mi 19. Nov 2014, 16:36 
Offline

Registriert: Mo 7. Okt 2013, 08:00
Beiträge: 36
Noch ein Nachtrag bzw Verbesserungsvorschlag:
Der RTC-Chip hat einen Ausgang MFP. Leider ist dieser nicht mit dem LPC-3131 verbunden. Damit könnte man den LPC schlafen legen, und gesteuert über die RTC wieder aufwecken.

Viele Grüße

Tilman


Nach oben
 Profil  
 
BeitragVerfasst: So 23. Nov 2014, 15:14 
Offline

Registriert: Mo 7. Okt 2013, 08:00
Beiträge: 36
(zu b : Timer mit externem Flankentrigger-Eingang): Soweit ich es überblicke, können die Timer des LPC nicht mit einem externen Input-Pin verbunden werden. Lediglich ein PWM-Signal kann erzeugt und an einen Pin gelegt werden (für die Helligkeitssteuerung einer LCD-Backplane).
Weiss jemand der Leser im Form von einer Timerchip mit I2C-Schnittstelle zum uC hin ? Ich dachte erst an 1-Wire, aber der einziger Timer ist abgekündigt und wird nicht mehr produziert (DS2423).

Danke und Gruß
Tilman


Nach oben
 Profil  
 
BeitragVerfasst: Mo 15. Dez 2014, 16:43 
Offline

Registriert: Mo 7. Okt 2013, 08:00
Beiträge: 36
Hallo

bezüglich des Wakeups habe ich ein bisschen in UM10314.pdf (User Manual des LPC 3131) Kapitel 17 (Event Router) gelesen:

Wenn man zum Beispiel für GPIO14 einen Event erzeugen (Interrupt) möchte, der den LPC aus dem Schlaf holt,
muss man meines Erachtens
mask[1].Bit29 auf 1
mask_set[1].Bit29 auf 1
apr[1].Bit29 auf 1 (damit löst ein HIGH Pegel bzw. eine steigende Flanke den Interrupt aus)
atr[1].Bit29 auf 1 (das schaltet den Latch zum Flakentriggern ein)
intoutMaskSet[4][1] Bit 29 auf 1 setzen, so dass der CGU durch das Signal und den daraus resultierenden Interrupt reaktiviert wird.

Ich habe mir die CGU nicht in der Tiefe angeschaut -- möglicher Weise würde das schon funktionieren.
a) Wie sehen das die anderen Teilnehmer des Forums ?
b) Wie programmiert man das ? Als Kernelmodul ? Oder geht es irgendwie über die giolib.c, deren Idee ich bislang nur ansatzweise verstehe ? Oder gibt es auch Wege aus dem Userspace ?

Ausserdem habe probiert, den gnublin wie oben beschrieben in Schlaf zu versetzen und wieder aufzuwecken. Das funktioniert natürlich nicht, da mI2STX_BCK0 ja nicht verbunden ist. Man muss ihn mittels Reset-Knopf wieder aus dem Schlaf reissen und rebooten.

Danke und Gruß
Tilman


Nach oben
 Profil  
 
BeitragVerfasst: Mo 15. Dez 2014, 19:31 
Offline

Registriert: Di 26. Jun 2012, 10:27
Beiträge: 172
Auf die Speicherregister kannst du über Kernelmodule oder über MemoryMap zugreifen.


Nach oben
 Profil  
 
BeitragVerfasst: Sa 10. Jan 2015, 01:16 
Offline

Registriert: Mo 7. Okt 2013, 08:00
Beiträge: 36
Hallo

ich habe ein kleines Programm geschrieben, dass GPIO15 aktiv schalten soll (d.h. Resume bei LOW.Pegel). Funktioniert leider nicht, d.h. nach echo "mem" > /sys/power/state, und Setzen eines Low-Pegels passiert nichts. Unten der Code -- für Ideen wäre ich dankbar.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
 
/* LPC3131 UM chapter 15 */
#define IOCONFIG1    0x13003000
#define FBLO_GPIO   0x1C0  /* GPIO functional block */
 
/* offset in GPIO functional block  */
#define PINS        0x00
#define MODE0       0x10 
#define MODE0_SET   0x14
#define MODE0_RESET 0x18
#define MODE1       0x20 
#define MODE1_SET   0x24
#define MODE1_RESET 0x28
 
/* !! Warning !!
 * GPIO4 (1 << 4) is only as INPUT available.
 * Setting the MODE0-Register for Pin 4 to 1 will cause a crash of the system!
 */
#define GPIO3   (1 << 3)
 
#define LED        GPIO3

/* LPC3131 UM chapter 17 event route */
#define IOCONFIG2    0x13000000
#define IOCONFIG3    0x13001000
#define EVENT_REGISTER 0x0C00
#define EVENT_PEND 0x0C00
#define EVENT_INT_CLR 0x0C20
#define EVENT_INT_SET 0x0C40
#define EVENT_MASK 0x0C60
#define EVENT_MASK_CLR 0x0C80
#define EVENT_MASK_SET 0x0CA0
#define EVENT_APR 0x0CC0
#define EVENT_ATR 0x0CE0
#define EVENT_RSR 0x0D20
#define EVENT_INOUT 0x0D40

#define EVENT_INOUTPEND 0x0000
#define EVENT_INOUTMASK 0x0400
#define EVENT_INOUTMASKCLR 0x0800
#define EVENT_INOUTMASKSET 0x0C00

#define EVENT_GPIO15 0x40000000

void byebye(void);
 
char *mymem1;
char *mymem2;
char *mymem3;


int main(int argc, char *argv[])
{
  int mem_fd1;
  int mem_fd2;
  int mem_fd3;
  unsigned int temp = 0;
  int enable_print = 0;

  atexit(byebye);
  if ((mem_fd1 = open("/dev/mem", O_RDWR)) < 0) {
    printf("can't open /dev/mem \n");
    exit(-1);
  }
  if ((mem_fd2 = open("/dev/mem", O_RDWR)) < 0) {
    printf("can't open /dev/mem \n");
    exit(-1);
  }
  if ((mem_fd3 = open("/dev/mem", O_RDWR)) < 0) {
    printf("can't open /dev/mem \n");
    exit(-1);
  }

  printf("mem_fd1 = %d,mem_fd2 = %d,mem_fd3 = %d\n",
         mem_fd1,mem_fd2,mem_fd3);
  printf("getpagesize() -> %d\n", getpagesize());
  mymem1 = mmap(0,
               getpagesize(),
               PROT_READ|PROT_WRITE,
               MAP_SHARED,
               mem_fd1,
               IOCONFIG1);
  if (mymem1 == MAP_FAILED) {
    printf("mmap error %d\n", errno);
    exit(-1);
  }
  else {
    printf("mymem1 = 0x%x\n", (unsigned int )mymem1);
  }
 mymem2 = mmap(0,
               getpagesize(),
               PROT_READ|PROT_WRITE,
               MAP_SHARED,
               mem_fd2,
               IOCONFIG2);
  if (mymem2 == MAP_FAILED) {
    printf("mmap error %d\n", errno);
    exit(-1);
  }
  else {
    printf("mymem2 = 0x%x\n", (unsigned int )mymem2);
  }
  mymem3 = mmap(0,
               getpagesize(),
               PROT_READ|PROT_WRITE,
               MAP_SHARED,
               mem_fd3,
               IOCONFIG3);
  if (mymem3 == MAP_FAILED) {
    printf("mmap error %d\n", errno);
    exit(-1);
  }
  else {
    printf("mymem3 = 0x%x\n", (unsigned int )mymem3);
  }

  if (argc > 1)
   enable_print = 1;

  // Setup event router
  printf("Setup event router\n");
  // clear GPIO15 interrupt as a precaution
  *(unsigned int *)(mymem2 + EVENT_INT_CLR + 1) = EVENT_GPIO15; 
  printf("Mark1\n");

  // ENABLE GPIO15 via MASK register
  printf("ENABLE Interrupt of GPIO 15 via MASK register\n");

  unsigned int buffer;
  *(unsigned int *)(mymem2 + EVENT_MASK_SET + 1) = EVENT_GPIO15;
  printf("Mark3\n");
// Activation polarity register: Set GPIO15 to LOW sensitiv
  buffer = *(unsigned int *)(mymem2 + EVENT_APR + 1);
  *(unsigned int *)(mymem2 + EVENT_APR + 1) = buffer & ~(EVENT_GPIO15);
  printf("Mark4\n");

  // Activation type register: Set GPIO15 to direct
  buffer = *(unsigned int *)(mymem2 + EVENT_ATR + 1);
  *(unsigned int *)(mymem2 + EVENT_ATR + 1) = buffer & ~(EVENT_GPIO15);
  printf("Mark5\n");

  // Connect GPIO15 to CGU_WakeUp interrupt
  // 4 (CGU_Interrupt) * 4 bytes + 1 (bank 1)
  *(unsigned int *)(mymem3 + EVENT_INOUTMASKSET + 16 + 1) =  EVENT_GPIO15;
  printf("Mark6\n");

  buffer = *(unsigned int *)(mymem3 + EVENT_INOUTMASK + 16 + 1);
  printf("EVENT_INOUTMASK: %u\n",buffer);

  *(unsigned int *)(mymem1 + FBLO_GPIO + MODE1_SET) = LED;
  while (1) {
    if (enable_print)
    {
      printf("=================================\n");
      printf("LED on\n");
    }
    *(unsigned int *)(mymem1 + FBLO_GPIO + MODE0_SET) = LED;
    temp = (*(unsigned int * )(mymem1 + FBLO_GPIO + PINS)) & LED;
    if (enable_print)
    {
      printf("READ GPIO %d\n", temp);
      printf("=================================\n");
    }
    sleep(1);
    if (enable_print)
    {
      printf("=================================\n");
      printf("LED off\n");
    }
    *(unsigned int *)(mymem1 + FBLO_GPIO + MODE0_RESET) = LED;
    temp = (*(unsigned int * )(mymem1 + FBLO_GPIO + PINS)) & LED;
    if (enable_print)
   {
      printf("READ GPIO %d\n", temp);
      printf("=================================\n");
    }
    sleep(1);

   // clear GPIO15 interrupt (regardless of whether it is set
   *(unsigned int *)(mymem2 + EVENT_INT_CLR + 1) = EVENT_GPIO15; 

  }
  return 0;
}
 
void byebye()
{
  printf("cleaning up\n");
  /* when not explicitly given, munmap() will automatically
     be called on exit (see 'man munmap') */
  munmap(mymem1, getpagesize());
  munmap(mymem2, getpagesize());
  munmap(mymem3, getpagesize());

}




Danke und Gruß

Tilman


Nach oben
 Profil  
 
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 10 Beiträge ] 

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
cron
Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de