From aa97a7ac78dbe529888662e3ffdc207b172c5a2c Mon Sep 17 00:00:00 2001 From: termitt Date: Sun, 27 Apr 2008 02:59:33 +0000 Subject: [PATCH] hcan2.c : some bug fixes, IRQ read optimalisation open.c : pre_read_config is called once for each message object not only when configuring chip --- lincan/src/hcan2.c | 44 ++++++++++++++++++++++---------------------- lincan/src/open.c | 12 +++++++++++- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/lincan/src/hcan2.c b/lincan/src/hcan2.c index a31490f..e960685 100644 --- a/lincan/src/hcan2.c +++ b/lincan/src/hcan2.c @@ -311,18 +311,19 @@ int hcan2_standard_mask(struct canchip_t *chip, unsigned short code, unsigned sh else return -ENODEV; - chip->chip_data = (void*)0; /* reset mbox number */ + chip->chip_data = (void*)0; /* reset mbox number */ ctrl0 = ((code & 0x07ff) << 4); lafm0 = ((mask & 0x07ff) << 4); + lafm0 |= 0x0003; /* ignore Ext ID 17:16 */ can_write_reg_w(chip, ctrl0, (int) obj->obj_base_addr + HCAN2_MB_CTRL0); can_write_reg_w(chip, 0x0000, (int) obj->obj_base_addr + HCAN2_MB_CTRL1); can_write_reg_w(chip, lafm0, (int) obj->obj_base_addr + HCAN2_MB_MASK); can_write_reg_w(chip, 0xffff, (int) obj->obj_base_addr + HCAN2_MB_MASK + 2); - DEBUGMSG("Set standard_mask [id:0x%04x, m:0x%04x]\n", code, mask); + DEBUGMSG("MB%02d: Set standard_mask [id:0x%04x, m:0x%04x]\n", obj_idx, code, lafm0); return 0; } @@ -355,7 +356,7 @@ int hcan2_extended_mask(struct canchip_t *chip, unsigned long code, unsigned lon can_write_reg_w(chip, lafm0, (int) obj->obj_base_addr + HCAN2_MB_MASK); can_write_reg_w(chip, lafm1, (int) obj->obj_base_addr + HCAN2_MB_MASK + 2); - DEBUGMSG("Set extended_mask [id:0x%08x, m:0x%08x]\n", (uint32_t)code, (uint32_t)mask); + DEBUGMSG("MB%02d: Set extended_mask [id:0x%08x, m:0x%08x]\n", obj_idx, (uint32_t)code, (uint32_t)mask); return 0; } @@ -454,25 +455,24 @@ int hcan2_irq_handler(int irq, struct canchip_t *chip) /* Received message */ if (irq_reg & HCAN2_IRR_DFRI) { - rxdf = (can_read_reg_w(chip, HCAN2_RXPR1) << 16) + - can_read_reg_w(chip, HCAN2_RXPR0); + rxdf = (can_read_reg_w(chip, HCAN2_RXPR1) << 16) + + can_read_reg_w(chip, HCAN2_RXPR0); - DEBUGMSG("Received message [0x%08x]\n", rxdf); + while(rxdf) { + DEBUGMSG("Received message [0x%08x]\n", rxdf); - while (rxdf) { /* find the message object */ - for (idx = 0; (idx < chip->max_objects) && !(rxdf & (1<max_objects) { - hcan2_irq_read_handler(chip, chip->msgobj[idx]); - - /* clear RXPR flag for this msgobj */ - can_write_reg_w(chip, (1 << (idx % 16)), HCAN2_RXPR0 - 2*(idx / 16)); - - rxdf = (can_read_reg_w(chip, HCAN2_RXPR1) << 16) + + for (idx = 0; (idx < chip->max_objects) && rxdf; idx++) + if ((rxdf & (1<msgobj[idx]); + /* RXPR flag for this msgobj is cleared during irq_read_handler*/ + rxdf &= ~(1 << idx); + } + + + DEBUGMSG("Before reset flags [0x%08x]\n", rxdf); + rxdf = (can_read_reg_w(chip, HCAN2_RXPR1) << 16) + can_read_reg_w(chip, HCAN2_RXPR0); - } } } @@ -695,22 +695,22 @@ void hcan2_irq_read_handler(struct canchip_t *chip, struct msgobj_t *obj) } else obj->rx_msg.id = (ctrl0 & HCAN2_MBCT0_STDID)>>4; - + if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH; for (i = 0; i < len; i++) { /* rcanqueue_ends_filt_conjuctionead 16bit data - two data bytes*/ data = can_read_reg_w(chip, (int) obj->obj_base_addr + HCAN2_MB_DATA1 + i); - obj->rx_msg.data[i] = (data & 0xff00) >> 8; - if (++i < len) obj->rx_msg.data[i] = data & 0x00ff; + obj->rx_msg.data[i] = (data & 0xff00) >> 8; // one data byte + if (++i < len) obj->rx_msg.data[i] = data & 0x00ff; // second data byte } /* Computes correct offset address of register from MSGBOX_IDX and RTR flag * result is one of these: * HCAN2_RXPR1, HCAN2_RXPR0, HCAN2_RFPR1, HCAN2_RFPR0 */ - flag_addr = ((ctrl0 & HCAN2_MBCT0_RTR) << 3) + HCAN2_RXPR0 - ((obj->object - 1) / 16) * 2; + flag_addr = HCAN2_RXPR0 - (int)((obj->object - 1) / 16) * 2; /* Reset flag by writing 1 to its position */ can_write_reg_w(chip, (1 << ((obj->object - 1) % 16)), flag_addr); diff --git a/lincan/src/open.c b/lincan/src/open.c index 45406fc..76fb9ee 100644 --- a/lincan/src/open.c +++ b/lincan/src/open.c @@ -24,6 +24,7 @@ int can_open(struct inode *inode, struct file *file) struct canque_ends_t *qends; struct canque_edge_t *edge; can_spin_irqflags_t iflags; + char openflag; // Martin Petera: Object already opened if ( ((obj=objects_p[MINOR_NR]) == NULL) || ((chip=objects_p[MINOR_NR]->hostchip) == NULL) ) { @@ -33,6 +34,7 @@ int can_open(struct inode *inode, struct file *file) atomic_inc(&obj->obj_used); DEBUGMSG("Device %d opened %d times.\n", MINOR_NR, atomic_read(&obj->obj_used)); + openflag = can_msgobj_test_fl(obj,OPENED); // Martin Petera: store previous status can_msgobj_set_fl(obj,OPENED); if (chip->flags & CHIP_CONFIGURED) @@ -42,11 +44,19 @@ int can_open(struct inode *inode, struct file *file) CANMSG("Error configuring chip.\n"); else chip->flags |= CHIP_CONFIGURED; + } /* End of chip configuration */ + + /* Martin Petera: Fix for HCAN2 + * pre_read was called only once -> Opening second MSG object from userspace + * didn't call function to configure MSG object for receive. + * FIX: Call pre_read once for each MSG object + **/ + if (!openflag) { if (chip->chipspecops->pre_read_config(chip,obj)<0) CANMSG("Error initializing chip for receiving\n"); + } - } /* End of chip configuration */ canuser = (struct canuser_t *)kmalloc(sizeof(struct canuser_t), GFP_KERNEL); if(canuser == NULL) goto no_canuser; -- 2.39.2