TOP
SSV Software Systems Register  Register
Log in to check your private messages  Log in to check your private messages
Startseite FAQ Search Mitglieder Profile  Log in 
SSV Support-Forum
Assembler

 
Post new topic   Reply to topic    SSV-Forum Forum Index >>> DNP/9200
<<< Previous topic - Next topic >>>  
Display posts from previous:   
Author Message
zeiro



Joined: 11 Feb 2009
Posts: 4

PostPosted: 01.07.2009, 15:28    Post subject: Assembler Reply with quote

Ich möchte einen Interrupt programmieren, dabei habe ich mich als Vorlage an das Dokument Interrupt Generation www.atmel.com/dyn/resources/prod_documents/doc2683.pdf gehalten. Nun ist hier der Interrupt in Assembler geschrieben. Meine Frage ist nun welchen GNU-Assambler nehmen ich dazu? Den /usr/local/arm/2.95.2/bin/arm-linux-as ?
Auch würde ich gerne wissen ob der Interrupt auch in C geschrieben werden kann, im SSV-Linux Control Kochbuch steht dazu: ... Eine Ausnahme bildet häufig das Programmieren eines Interrupt-Treibers für eine MSR-Anwendung. Solche Softwarekomponenten werden in der Regel in Assembler erstellt.
Back to top
View user's profile Send private message
Ole



Joined: 26 Nov 2008
Posts: 20

PostPosted: 13.07.2009, 15:37    Post subject: Reply with quote

Hallo Zeiro!


Ich habe das Timer Counter Programm mal in einen Kernel modul (C) gepackt:

at_timercounter.c:
Code:

/*
 * Author  : Ole Loots
 * Date    : 24.02.2009
 * Version : 1.00
 * License : GPL
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/time.h>
#include <asm/irq.h>
#include <linux/platform_device.h>
#include <linux/ioctl.h>
#include <asm/hardware.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
#include <asm-arm/arch-at91rm9200/hardware.h>
#include <asm-arm/arch-at91rm9200/at91rm9200_tc.h>
#include <asm-arm/arch-at91rm9200/at91rm9200.h>
#include <asm-arm/arch-at91rm9200/memory.h>
#include <asm/uaccess.h>
#include <asm/arch/hardware.h>
#include <asm/mach/time.h>

#include "at91_timer.h"

/*
    Prototypes
*/
static int setup_timer_irq(void);
static int reset_device(void);

/*
*
*  Global Variables
*/

static int timer_used = 0;
//AD_DATAPOINT current_dp_ch[2];

long (*p_sys_clock_gettime)(clockid_t, struct timespec *tp) = (unsigned long *) 0xc004373c;   // function pointer to sys_clock_gettime

#ifdef MODULE_AUTHOR
 MODULE_AUTHOR("Ole Loots");
 MODULE_DESCRIPTION("Kernel Timerchannel interrupt module for DNP/9200");
 MODULE_LICENSE("GPL");
#endif

/* ioctl method - ioctl(device, SSVIRQ_SETPOINTER, &irqcount)... */

/* open method - device = open("/dev/ssvirq", O_RDWR)... */
static int timercounter_open(struct inode * inode, struct file * file) {

    /* only one program could open the device */
    if (timer_used != 0) {
   return -EBUSY;
    }
    timer_used = 1;
    return 0;
}

/* close method - close(device)... */
static int timercounter_release(struct inode * inode, struct file * file) {
    timer_used = 0;
    return 0;
}

static struct file_operations ad_irq_fops = {
   owner:      THIS_MODULE,
    open:      timercounter_open,
    release:   timercounter_release,
};

/* unload kernel module - rmmod ssvirq... */
static void __exit timercounter_cleanup(void) {

    /* unregister irq handler */
   free_irq(AT91_ID_TC0, NULL);

    /* unregister character device handler */
    unregister_chrdev(AT91_TIMERCOUNTER_MAJOR, AT91_TIMERCOUNTER_DEVICE_NAME);
    printk(KERN_INFO "%s module removed.\n", AT91_TIMERCOUNTER_DEVICE_NAME);
}

/*
 * Read from Timerblock 0 registers.
 */
static inline unsigned long at91_tcb1_read(unsigned int reg){
   void __iomem *tcb1_base = (void __iomem *)AT91_VA_BASE_TCB0;
   return __raw_readl(tcb1_base + reg);
}

/*
 * Write to Timerblock 0 registers.
 */
static inline void at91_tcb1_write(unsigned int reg, unsigned long value){
   void __iomem *tcb1_base = (void __iomem *)AT91_VA_BASE_TCB0;
   __raw_writel(value, tcb1_base + reg);
}


/* irq handler timer 1 */
irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
   struct timespec tp;

   p_sys_clock_gettime(CLOCK_REALTIME, &tp);
   
   // read & clear status:
   at91_tcb1_read(AT91_TC0 + AT91_TC_SR);
   return(IRQ_HANDLED);
}

/*
*  timer channel interrupt setup
*/
static int setup_timer_irq( void ){
   // disable clock:
   at91_tcb1_write(AT91_TC0 + AT91_TC_CCR,  ((at91_tcb1_read(AT91_TC0 + AT91_TC_CCR) | 2) ) );

   // disable all Timer Channel 0 interrupts:
   at91_tcb1_write(AT91_TC0 + AT91_TC_IDR, 0xFFFFFFFF  );

   // read & clear status:
   at91_tcb1_read(AT91_TC0 + AT91_TC_SR );

   // enable timer clock 5, reset counter and start clock
   at91_tcb1_write(AT91_TC0 + AT91_TC_CMR, AT91_TC_TIMER_CLOCK5 |  AT91_TC_CPCTRG | !AT91_TC_WAVE );

   // Enables the RC Compare Interrupt:
   at91_tcb1_write(AT91_TC0 + AT91_TC_IER, 0x10 );

   if (request_irq(AT91_ID_TC0, (void *)timer_interrupt, 0 ,AT91_TIMERCOUNTER_DEVICE_NAME, NULL)) {
           printk(KERN_ERR "ad_irq: irq alrdy claimed!\n");
      return -EIO;
    }
   // write something to timer register c:
   at91_tcb1_write( AT91_TC0 + AT91_TC_RC , 0xFBC5 );

   // enable & start clock
   at91_tcb1_write(AT91_TC0 + AT91_TC_CCR , 0x01 );
   at91_tcb1_write(AT91_TC0 + AT91_TC_CCR , 0x05 );
   return(0);
}


static int reset_device(void)
{
   timer_used= 0;
}


static int __init timercounter_init(void)
{
   int ret;

   reset_device();
   
    ret = setup_timer_irq();
   if(ret != 0)
   {
        return(ret);
   }
    /* register character device handler */
   
    if (register_chrdev(AT91_TIMERCOUNTER_MAJOR,AT91_TIMERCOUNTER_DEVICE_NAME,&ad_irq_fops)) {
      printk(KERN_ERR "%s: unable to get major %d\n", AT91_TIMERCOUNTER_DEVICE_NAME, AT91_TIMERCOUNTER_MAJOR);
      free_irq(AT91_ID_TC0, NULL);
      return -EIO;
    }
    printk(KERN_INFO "%s module installed with irqnr=%d\n", AT91_TIMERCOUNTER_DEVICE_NAME,AT91_ID_TC0);
    return 0;
}


module_init(timercounter_init);
module_exit(timercounter_cleanup);


at_timercounter.h:
Code:

struct at91_timer_channel
{
   unsigned long ccr;            // channel control register      (WO)
   unsigned long cmr;            // channel mode register      (RW)
   unsigned long reserved[2];      
   unsigned long cv;            // counter value            (RW)
   unsigned long ra;            // register A               (RW)
   unsigned long rb;            // register B               (RW)
   unsigned long rc;            // register C               (RW)
   unsigned long sr;            // status register            (RO)
   unsigned long ier;            // interrupt enable register   (WO)
   unsigned long idr;            // interrupt disable register   (WO)
   unsigned long imr;            // interrupt mask register      (RO)
};

struct at91_timers
{
   struct {
      struct at91_timer_channel ch;
      unsigned char padding[0x40-sizeof(struct at91_timer_channel)];
   } chans[3];
   unsigned  long bcr;            // block control register      (WO)
   unsigned  long bmr;            // block mode    register      (RW)
};

/*  TC control register */
#define TC_SYNC   (1)

/*  TC mode register */
#define TC2XC2S(x)   (x & 0x3)
#define TC1XC1S(x)   (x<<2 & 0xc)
#define TC0XC0S(x)   (x<<4 & 0x30)
#define TCNXCNS(timer,v) ((v) << (timer<<1))

/* TC channel control */
#define TC_CLKEN   (1)         
#define TC_CLKDIS   (1<<1)         
#define TC_SWTRG   (1<<2)         

/* TC interrupts enable/disable/mask and status registers */
#define TC_MTIOB   (1<<18)
#define TC_MTIOA   (1<<17)
#define TC_CLKSTA   (1<<16)

#define TC_ETRGS   (1<<7)
#define TC_LDRBS   (1<<6)
#define TC_LDRAS   (1<<5)
#define TC_CPCS      (1<<4)
#define TC_CPBS      (1<<3)
#define TC_CPAS      (1<<2)
#define TC_LOVRS   (1<<1)
#define TC_COVFS   (1)

#define AT91_TC0 0x00
#define AT91_TC1 0x40
#define AT91_TC2 0x80

#define AT91_TC3 0x00
#define AT91_TC4 0x40
#define AT91_TC5 0x80

#define AT91_TIMERCOUNTER_MAJOR 124

#define AT91_TIMERCOUNTER_DEVICE_NAME "at91_timercounter"
#define __invalid_size_argument_for_IOC 1

Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    SSV-Forum Forum Index >>> DNP/9200 All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

SSV Software Systems GmbH

Dünenweg 5
30419 Hannover

Fon: +49(0)511  ·  40 000-0
Fax: +49(0)511  ·  40 000-40

sales@ssv-embedded.de


Impressum    ·    Datenschutz    ·    AGB

© 2023 SSV SOFTWARE SYSTEMS GmbH. Alle Rechte vorbehalten.

ISO 9001:2015