#include "hal_machperiph.h"
#include "cpu_def.h"
#include "system_def.h"
+
+#include "can/can.h"
#include "can/canmsg.h"
#ifdef __cplusplus
#define CAN1TDB3 (*(uint32_t*)(CAN1_REGS_BASE+CAN_TDB3_o))
+//----------------------------------
+
+//CAN Interrupt and Capture Register bits
+#define CAN_ICR_TI1 (1<<1)
+
+//CAN Status Register bits
+#define CAN_SR_TBS1 (1<<2)
+
+//CAN Command Register bits
+#define CAN_CMR_TR (1<<0)
+#define CAN_CMR_AT (1<<1)
+#define CAN_CMR_RRB (1<<2)
+#define CAN_CMR_CDO (1<<3)
+#define CAN_CMR_STB1 (1<<5)
+
+//CAN Transmit Frame Information register 1 bits
+#define CAN_TFI1_RTR (1<<30)
+#define CAN_TFI1_EXT (1<<31)
+
+//CAN Interrupt Enable Register bits
+#define CAN_IER_TIE1 (1<<1)
+
//----------------------------------
#define PCONP SC->PCONP
void CAN_init(uint32_t baudrate);
void CAN_send(canmsg_t* msg);
+void CAN_IRQHandler(void);
+
+//----------------------------------
+
+struct can_lmc1_chip_data
+{
+ int flags;
+};
+
+// board can-lmc1 specific functions:
+int can_lmc1_register(struct hwspecops_t *hwspecops);
+int can_lmc1_init_hw_data(struct candevice_t *candev);
+int can_lmc1_init_chip_data(struct candevice_t *candev, int chipnr);
+int can_lmc1_init_obj_data(struct canchip_t *chip, int objnr);
+void can_lmc1_write_register(unsigned data, unsigned long address);
+unsigned can_lmc1_read_register(unsigned long address);
+int can_lmc1_request_io(struct candevice_t *candev);
+int can_lmc1_reset(struct candevice_t *candev);
+
+// lpc17xx can chip specific functions:
+int lpc17xx_chip_config(struct canchip_t *chip);
+int lpc17xx_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
+ struct canmsg_t *msg);
+int lpc17xx_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
+ struct canmsg_t *msg);
+int lpc17xx_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj);
+int lpc17xx_irq_handler(int irq, struct canchip_t *chip);
+void lpc17xx_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj);
+int lpc17xx_fill_chipspecops(struct canchip_t *chip);
+int lpc17xx_register(struct chipspecops_t *chipspecops);
+int lpc17xx_attach_to_chip(struct canchip_t *chip);
+int lpc17xx_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj);
#ifdef __cplusplus
}
static void CAN_configPin();
static void CAN_setBusTiming(uint32_t baudrate);
-//------------------------------------------
+extern struct canhardware_t *hardware_p;
+
+//---------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------
+
+// interrupt handler
+// now only for transmitting - irq when one message was transmitted (for check if another message is pending in can msg queue)
+
+void CAN_IRQHandler(){
+
+ uint32_t i;
+
+ i = CAN1ICR;
+ if(!(i & CAN_ICR_TI1))
+ return;
+
+
+ struct canchip_t *chip;
+ chip = hardware_p->candevice[0]->chip[0];
+
+ lpc17xx_irq_handler(0, chip);
+
+}
+
+
+//---------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------
+
+
+// board can-lmc1 specific functions:
+
+int can_lmc1_register(struct hwspecops_t *hwspecops){
+
+ hwspecops->request_io = can_lmc1_request_io;
+ hwspecops->reset = can_lmc1_reset;
+ hwspecops->init_hw_data = can_lmc1_init_hw_data;
+ hwspecops->init_chip_data = can_lmc1_init_chip_data;
+ hwspecops->init_obj_data = can_lmc1_init_obj_data;
+ hwspecops->write_register = can_lmc1_write_register;
+ hwspecops->read_register = can_lmc1_read_register;
+
+ return 0;
+}
+
+int can_lmc1_init_hw_data(struct candevice_t *candev){
+
+ candev->res_addr=0;
+ candev->nr_82527_chips=0;
+ candev->nr_sja1000_chips=0;
+ candev->nr_all_chips=1;
+ candev->flags |= 0;
+
+ return 0;
+}
+
+int can_lmc1_init_chip_data(struct candevice_t *candev, int chipnr){
+
+ lpc17xx_fill_chipspecops(candev->chip[chipnr]);
+
+ candev->chip[chipnr]->flags|= CHIP_IRQ_CUSTOM;
+
+ candev->chip[chipnr]->chip_data=(void *)malloc(sizeof(struct can_lmc1_chip_data));
+ if (candev->chip[chipnr]->chip_data==NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
+int can_lmc1_init_obj_data(struct canchip_t *chip, int objnr){
+
+ //chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10;
+
+ return 0;
+}
+
+void can_lmc1_write_register(unsigned data, unsigned long address){
+
+ printf("UNSUPPORTED NOW\n");
+
+}
+
+unsigned can_lmc1_read_register(unsigned long address){
+
+ printf("UNSUPPORTED NOW\n");
+
+}
+
+int can_lmc1_request_io(struct candevice_t *candev)
+{
+ return 0;
+}
+
+int can_lmc1_reset(struct candevice_t *candev)
+{
+ return 0;
+}
+
+
+//---------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------
+
+
+// lpc17xx can chip specific functions:
+
+
+int lpc17xx_chip_config(struct canchip_t *chip){
+
+ CAN_init( (uint32_t) chip->baudrate);
+
+ return 0;
+}
+
+int lpc17xx_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
+ struct canmsg_t *msg)
+{
+
+ CAN_send(msg);
+
+ return 0;
+}
+
+int lpc17xx_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
+ struct canmsg_t *msg)
+{
+
+ // write transmission request
+ CAN1CMR = (CAN_CMR_TR | CAN_CMR_STB1);
+
+ return 0;
+}
+
+int lpc17xx_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
+{
+
+ can_preempt_disable();
+
+ can_msgobj_set_fl(obj,TX_PENDING);
+ can_msgobj_set_fl(obj,TX_REQUEST);
+
+ while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
+ can_msgobj_clear_fl(obj,TX_REQUEST);
+
+
+ if (CAN1SR & CAN_SR_TBS1){
+ obj->tx_retry_cnt=0;
+ lpc17xx_irq_write_handler(chip, obj);
+ }
+
+ can_msgobj_clear_fl(obj,TX_LOCK);
+ if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
+
+ }
+
+ can_preempt_enable();
+
+ return 0;
+}
+
+int lpc17xx_irq_handler(int irq, struct canchip_t *chip)
+{
+
+ struct msgobj_t *obj;
+ obj = chip->msgobj[0];
+
+
+ if ((can_msgobj_test_fl(obj,TX_PENDING)) || (can_msgobj_test_fl(obj,TX_REQUEST))) {
+
+ can_msgobj_set_fl(obj,TX_REQUEST);
+
+ while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
+
+ obj->ret=0;
+ can_msgobj_clear_fl(obj,TX_REQUEST);
+
+ if (CAN1SR & CAN_SR_TBS1){
+ obj->tx_retry_cnt=0;
+ lpc17xx_irq_write_handler(chip, obj);
+ }
+
+ can_msgobj_clear_fl(obj,TX_LOCK);
+ if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
+
+ }
+ }
+
+ return CANCHIP_IRQ_HANDLED;
+
+}
+
+void lpc17xx_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
+{
+ int cmd;
+
+ if(obj->tx_slot){
+ /* Do local transmitted message distribution if enabled */
+ if (processlocal){
+ /* fill CAN message timestamp */
+ can_filltimestamp(&obj->tx_slot->msg.timestamp);
+
+ obj->tx_slot->msg.flags |= MSG_LOCAL;
+ canque_filter_msg2edges(obj->qends, &obj->tx_slot->msg);
+ }
+ /* Free transmitted slot */
+ canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+ obj->tx_slot=NULL;
+ }
+
+ can_msgobj_clear_fl(obj,TX_PENDING);
+ cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot);
+ if(cmd<0)
+ return;
+ can_msgobj_set_fl(obj,TX_PENDING);
+
+ if (chip->chipspecops->pre_write_config(chip, obj, &obj->tx_slot->msg)) {
+ obj->ret = -1;
+ canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_PREP);
+ canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+ obj->tx_slot=NULL;
+ return;
+ }
+ if (chip->chipspecops->send_msg(chip, obj, &obj->tx_slot->msg)) {
+ obj->ret = -1;
+ canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_SEND);
+ canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+ obj->tx_slot=NULL;
+ return;
+ }
+
+}
+
+int lpc17xx_fill_chipspecops(struct canchip_t *chip){
+
+ chip->max_objects=1;
+ chip->baudrate=1000000;
+
+ lpc17xx_register(chip->chipspecops);
+ return 0;
+}
+
+int lpc17xx_register(struct chipspecops_t *chipspecops){
+
+ CANMSG("initializing lpc17xx can chip operations\n");
+
+ chipspecops->attach_to_chip = lpc17xx_attach_to_chip;
+ chipspecops->pre_read_config = lpc17xx_pre_read_config;
+ chipspecops->chip_config = lpc17xx_chip_config;
+ chipspecops->pre_write_config = lpc17xx_pre_write_config;
+ chipspecops->send_msg = lpc17xx_send_msg;
+ chipspecops->wakeup_tx = lpc17xx_wakeup_tx;
+ chipspecops->irq_handler = lpc17xx_irq_handler;
+
+ return 0;
+
+}
+
+
+int lpc17xx_attach_to_chip(struct canchip_t *chip){
+
+ return 0;
+}
+
+int lpc17xx_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj){
+
+ return 1;
+}
+
+
+
+//---------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------
+
static void CAN_configPin(){
uint32_t i;
// check status of TB1
- while (!(CAN1SR & (1<<2))){}
+ while (!(CAN1SR & CAN_SR_TBS1)){}
CAN1TFI1 &= ~0x000F0000;
CAN1TFI1 |= (msg->length)<<16;
// EXT frame
if(msg->flags & MSG_EXT)
- CAN1TFI1 |= (1<<31);
+ CAN1TFI1 |= CAN_TFI1_EXT;
else
- CAN1TFI1 &= ~(1<<31);
+ CAN1TFI1 &= ~CAN_TFI1_EXT;
// RTR frame
if(msg->flags & MSG_RTR)
- CAN1TFI1 |= (1<<30);
+ CAN1TFI1 |= CAN_TFI1_RTR;
else
- CAN1TFI1 &= ~(1<<30);
+ CAN1TFI1 &= ~CAN_TFI1_RTR;
// write CAN ID
CAN1TID1 = msg->id;
CAN1TDB1 = data;
// write transmission request
- CAN1CMR = 0x21;
+ //CAN1CMR = 0x21;
}
uint32_t pclksel0;
uint32_t val;
+ printf("CAN INIT, baudrate: %d\n", baudrate);
// configure CAN1 pins
CAN_configPin();
CAN1GSR = 0x3C;
// request command to release Rx, Tx buffer and clear data overrun
- CAN1CMR = (1<<1)|(1<<2)|(1<<3);
+ CAN1CMR = (CAN_CMR_AT | CAN_CMR_RRB | CAN_CMR_CDO);
// read to clear interrupt pending in Interrupt Capture Register
tmp = CAN1ICR;
// return to normal operating
CAN1MOD = 0;
+ // enable interrupt after transmit
+ CAN1IER |= CAN_IER_TIE1;
+ // enable CAN interrupt
+ NVIC_EnableIRQ(CAN_IRQn);
+
}
typedef void (*FNC)(); //function ptr
-
/***********************************************************************
* global variables
***********************************************************************/
sys_err();
}
-// !!! DEBUG - first version, only transmitting CAN messages withnout usage of queue system from LinCAN
-
- // CAN
- CAN_init(1000000);
- // CAN end
+// !!! DEBUG - first version, only transmitting CAN messages with usage of queue system from LinCAN
-/*
//***********************************************************************
// * CAN device initialization - device side (adapted from LinCAN setup.c)
// DEBUG
//can_init(); // only for successful compiling (defined in can_lpcbusemu.c)
-
-
DEBUGMSG("Initiating CAN device initialization\n");
}
memset(candev->hwspecops, 0, sizeof(struct hwspecops_t));
+
+
// DEBUG
//ul_usb1_register(candev->hwspecops); // only for successful compiling (defined in ul_usb1.c)
+ // register for another board
+ can_lmc1_register(candev->hwspecops);
+
bd=baudrate[0];
CANMSG("HW data could not be initialized\n");
sys_err();
}
+
// Alocate and initialize the chip structures
for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
// if(chipnr<irqnum)
sys_err();
}
}
+
+
+
for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
struct canchip_t *chip=candev->chip[chipnr];
int objnr;
if(m>=0) m++;
}
}
+
+
if (candev->hwspecops->request_io(candev))
sys_err();
candev->flags|=CANDEV_IO_RESERVED;
+
+
if (candev->hwspecops->reset(candev))
sys_err();
+
+
for(chipnr=0; chipnr<candev->nr_all_chips; chipnr++) {
if((chip=candev->chip[chipnr])==NULL)
continue;
// * CAN device initialization - client side (adapted from LinCAN open.c)
// ***********************************************************************
+
chip=candev->chip[0];
obj=chip->msgobj[0];
atomic_inc(&obj->obj_used);
} // End of chip configuration
+
canuser = (struct canuser_t *)malloc(sizeof(struct canuser_t));
if(canuser == NULL) sys_err();
canuser->flags=0;
canque_edge_decref(canuser->rx_edge0);
canque_edge_decref(edge);
-*/
+
/***********************************************************************
* USB Init
if (usb_device.ep_events & MASK_EP1RX) { //EP1RX - data waiting to receive
- // DEBUG - unused queue system (yet)
- //if (canque_get_inslot(qends, &qedge, &slot, 0)>=0){ //Free slot obtained
+ if (canque_get_inslot(qends, &qedge, &slot, 0)>=0){ //Free slot obtained
size=usb_udev_read_endpoint(&eps[0],ep1_rx_buff,16);
if (size==16){
/* Automatic selection of extended format if ID>2047 */
if (canmsg.id & ~0x7ffl & MSG_ID_MASK ) canmsg.flags |= MSG_EXT;
/* has been dependent on "extended" option */
-
- // DEBUG - unused queue system (yet)
- //slot->msg=canmsg;
- //canque_put_inslot(qends, qedge, slot);
- CAN_send(&canmsg);
+
+ slot->msg=canmsg;
+ canque_put_inslot(qends, qedge, slot);
+ //CAN_send(&canmsg);
}
-
- // DEBUG - unused queue system (yet)
- //else
- // canque_abort_inslot(qends,qedge,slot);
+ else
+ canque_abort_inslot(qends,qedge,slot);
+
timer_rx_off=50; //rosviceni diody pri prijmu
CLR_OUT_PIN(LED_PORT,LED2_BIT);
usb_device.ep_events &= ~MASK_EP1RX;
- // DEBUG
- //}
-
+
+ }
+
/* if (size==2){
uint8_t val;