etisserant@0: /* etisserant@0: This file is part of CanFestival, a library implementing CanOpen Stack. etisserant@0: etisserant@0: Copyright (C): Edouard TISSERANT and Francis DUPIN etisserant@0: etisserant@0: See COPYING file for copyrights details. etisserant@0: etisserant@0: This library is free software; you can redistribute it and/or etisserant@0: modify it under the terms of the GNU Lesser General Public etisserant@0: License as published by the Free Software Foundation; either etisserant@0: version 2.1 of the License, or (at your option) any later version. etisserant@0: etisserant@0: This library is distributed in the hope that it will be useful, etisserant@0: but WITHOUT ANY WARRANTY; without even the implied warranty of etisserant@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU etisserant@0: Lesser General Public License for more details. etisserant@0: etisserant@0: You should have received a copy of the GNU Lesser General Public etisserant@0: License along with this library; if not, write to the Free Software etisserant@0: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA etisserant@0: */ etisserant@0: frdupin@54: // Uncomment if you don't need console informations. etisserant@0: #define DEBUG_WAR_CONSOLE_ON etisserant@0: #define DEBUG_ERR_CONSOLE_ON etisserant@0: etisserant@0: #include /* for NULL */ etisserant@0: etisserant@0: #include etisserant@0: #include etisserant@0: #include etisserant@0: #include etisserant@0: frdupin@54: #include "../include/data.h" etisserant@0: #include etisserant@0: etisserant@0: etisserant@0: frdupin@54: #include "../include/hcs12/candriver.h" frdupin@54: #include "../include/hcs12/canOpenDriver.h" etisserant@0: #include "../include/def.h" etisserant@0: #include "../include/can.h" etisserant@0: #include "../include/objdictdef.h" etisserant@0: #include "../include/objacces.h" etisserant@0: #include "../include/sdo.h" etisserant@0: #include "../include/pdo.h" Edouard@801: #include "../include/timers.h" etisserant@0: #include "../include/lifegrd.h" etisserant@0: #include "../include/sync.h" etisserant@0: etisserant@0: #include "../include/nmtSlave.h" frdupin@61: frdupin@61: // File created by the GUI etisserant@0: #include "objdict.h" etisserant@0: frdupin@54: frdupin@54: frdupin@54: etisserant@0: etisserant@0: // HCS12 configuration etisserant@0: // ----------------------------------------------------- etisserant@0: etisserant@0: enum E_CanBaudrate etisserant@0: { etisserant@0: CAN_BAUDRATE_250K, etisserant@0: CAN_BAUDRATE_500K, etisserant@0: CAN_BAUDRATE_1M, etisserant@0: }; etisserant@0: etisserant@0: etisserant@0: const canBusTime CAN_Baudrates[] = etisserant@0: { etisserant@0: { etisserant@0: 1, /* clksrc: Use the bus clock : 16 MHz, the freq. of the quartz's board */ etisserant@0: 3, /* brp : chose btw 0 and 63 (6 bits). freq time quantum = 16MHz / (brp + 1) */ etisserant@0: 0, /* sjw : chose btw 0 and 3 (2 bits). Sync on (sjw + 1 ) time quantum */ etisserant@0: 0, /* samp : chose btw 0 and 3 (2 bits) (samp + 1 ) samples per bit */ etisserant@0: 1, /* tseg2 : chose btw 0 and 7 (3 bits) Segment 2 width = (tseg2 + 1) tq */ etisserant@0: 12, /* tseg1 : chose btw 0 and 15 (4 bits) Segment 1 width = (tseg1 + 1) tq */ etisserant@0: etisserant@0: /* etisserant@0: With these values, etisserant@0: - The width of the bit time is 16 time quantum : etisserant@0: - 1 tq for the SYNC segment (could not be modified) etisserant@0: - 13 tq for the TIME 1 segment (tseg1 = 12) etisserant@0: - 2 tq for the TIME 2 segment (tseg2 = 1) etisserant@0: - Because the bus clock of the MSCAN is 16 MHZ, and the etisserant@0: freq of the time quantum is 4 MHZ (brp = 3+1), and there are 16 tq in the bit time, etisserant@0: so the freq of the bit time is 250 kHz. etisserant@0: */ etisserant@0: }, etisserant@0: etisserant@0: { etisserant@0: 1, /* clksrc: Use the bus clock : 16 MHz, the freq. of the quartz's board */ etisserant@0: 1, /* brp : chose btw 0 and 63 (6 bits). freq time quantum = 16MHz / (brp + 1) */ etisserant@0: 0, /* sjw : chose btw 0 and 3 (2 bits). Sync on (sjw + 1 ) time quantum */ etisserant@0: 0, /* samp : chose btw 0 and 3 (2 bits) (samp + 1 ) samples per bit */ etisserant@0: 1, /* tseg2 : chose btw 0 and 7 (3 bits) Segment 2 width = (tseg2 + 1) tq */ etisserant@0: 12, /* tseg1 : chose btw 0 and 15 (4 bits) Segment 1 width = (tseg1 + 1) tq */ etisserant@0: etisserant@0: /* etisserant@0: With these values, etisserant@0: - The width of the bit time is 16 time quantum : etisserant@0: - 1 tq for the SYNC segment (could not be modified) etisserant@0: - 13 tq for the TIME 1 segment (tseg1 = 12) etisserant@0: - 2 tq for the TIME 2 segment (tseg2 = 1) etisserant@0: - Because the bus clock of the MSCAN is 16 MHZ, and the etisserant@0: freq of the time quantum is 8 MHZ (brp = 1+1), and there are 16 tq in the bit time, etisserant@0: so the freq of the bit time is 500 kHz. etisserant@0: */ etisserant@0: }, etisserant@0: etisserant@0: { etisserant@0: 1, /* clksrc: Use the bus clock : 16 MHz, the freq. of the quartz's board */ etisserant@0: 1, /* brp : chose btw 0 and 63 (6 bits). freq time quantum = 16MHz / (brp + 1) */ etisserant@0: 0, /* sjw : chose btw 0 and 3 (2 bits). Sync on (sjw + 1 ) time quantum */ etisserant@0: 0, /* samp : chose btw 0 and 3 (2 bits) (samp +MSG_WAR(0x3F33, "Je suis le noeud ", getNodeId()); 1 ) samples per bit */ etisserant@0: 1, /* tseg2 : chose btw 0 and 7 (3 bits) Segment 2 width = (tseg2 + 1) tq */ etisserant@0: 4, /* tseg1 : chose btw 0 and 15 (4 bits) Segment 1 width = (tseg1 + 1) tq */ etisserant@0: etisserant@0: /* etisserant@0: With these values, etisserant@0: - The width of the bit time is 16 time quantum : etisserant@0: - 1 tq for the SYNC segment (could not be modified) etisserant@0: - 5 tq for the TIME 1 segment (tseg1 = 4) etisserant@0: - 2 tq for the TIME 2 segment (tseg2 = 1) etisserant@0: - Because the bus clock of the MSCAN is 16 MHZ, and the etisserant@0: freq of the time quantum is 8 MHZ (brp = 1+1), and there are 8 tq in the bit time, etisserant@0: so the freq of the bit time is 1 MHz. etisserant@0: */ etisserant@0: } etisserant@0: }; etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: /**************************prototypes*****************************************/ etisserant@0: frdupin@54: //Init can bus and Canopen etisserant@0: void initCanopencapteur (void); frdupin@54: // Init the sensor etisserant@0: void initSensor(void); etisserant@0: void initPortB(void); frdupin@54: void initPortH(void); frdupin@54: etisserant@0: etisserant@0: //------------------------------------------------------------------------------ etisserant@0: //Initialisation of the port B for the leds. etisserant@0: void initPortB(void) etisserant@0: { etisserant@0: // Port B is output etisserant@0: IO_PORTS_8(DDRB)= 0XFF; etisserant@0: // RAZ etisserant@0: IO_PORTS_8(PORTB) = 0xFF; etisserant@0: } etisserant@0: frdupin@54: //------------------------------------------------------------------------------ frdupin@54: // Init of port H to choose the CAN rate by switch, and the nodeId frdupin@54: void initPortH(void) frdupin@54: { frdupin@54: // Port H is input frdupin@54: IO_PORTS_8(DDRH)= 0X00; frdupin@54: // Enable pull device frdupin@54: IO_PORTS_8(PERH) = 0XFF; frdupin@54: // Choose the pull-up device frdupin@54: IO_PORTS_8(PPSH) = 0X00; frdupin@54: } etisserant@0: etisserant@0: //------------------------------------------------------------------------------ etisserant@0: void initSensor(void) etisserant@0: { frdupin@54: UNS8 baudrate = 0; frdupin@54: UNS8 nodeId = 0; etisserant@0: // Init led control etisserant@0: initPortB(); etisserant@0: IO_PORTS_8(PORTB) &= ~ 0x01; //One led ON frdupin@54: initPortH(); frdupin@54: frdupin@54: /* Defining the node Id */ frdupin@54: // Uncomment to have a fixed nodeId frdupin@54: //setNodeId(&gene_SYNC_Data, 0x03); frdupin@54: frdupin@54: // Comment below to have a fixed nodeId frdupin@54: nodeId = ~(IO_PORTS_8(PTH)) & 0x3F; frdupin@54: if (nodeId == 0) { frdupin@54: MSG_WAR(0x3F33, "Using default nodeId : ", getNodeId(&gene_SYNC_Data)); frdupin@54: } frdupin@54: else frdupin@54: setNodeId(&gene_SYNC_Data, nodeId); frdupin@54: frdupin@54: MSG_WAR(0x3F33, "My nodeId is : ", getNodeId(&gene_SYNC_Data)); etisserant@0: etisserant@0: canBusInit bi0 = { etisserant@0: 0, /* no low power */ etisserant@0: 0, /* no time stamp */ etisserant@0: 1, /* enable MSCAN */ etisserant@0: 0, /* clock source : oscillator (In fact, it is not used) */ etisserant@0: 0, /* no loop back */ etisserant@0: 0, /* no listen only */ etisserant@0: 0, /* no low pass filter for wk up */ etisserant@0: CAN_Baudrates[CAN_BAUDRATE_250K], etisserant@0: { etisserant@0: 0x00, /* Filter on 16 bits. See Motorola Block Guide V02.14 fig 4-3 */ etisserant@0: 0x00, 0xFF, /* filter 0 hight accept all msg */ etisserant@0: 0x00, 0xFF, /* filter 0 low accept all msg */ etisserant@0: 0x00, 0xFF, /* filter 1 hight filter all of msg */ etisserant@0: 0x00, 0xFF, /* filter 1 low filter all of msg */ etisserant@0: 0x00, 0xFF, /* filter 2 hight filter most of msg */ etisserant@0: 0x00, 0xFF, /* filter 2 low filter most of msg */ etisserant@0: 0x00, 0xFF, /* filter 3 hight filter most of msg */ etisserant@0: 0x00, 0xFF, /* filter 3 low filter most of msg */ etisserant@0: } etisserant@0: }; etisserant@0: etisserant@0: //Init the HCS12 microcontroler for CanOpen etisserant@0: initHCS12(); etisserant@0: frdupin@54: // Chose the CAN rate (On our board, whe have switch for all purpose) frdupin@54: // 7 8 frdupin@54: // ON ON => 1000 kpbs frdupin@54: // OFF ON => 500 kpbs frdupin@54: // ON OFF => 250 kpbs frdupin@54: frdupin@54: baudrate = ~(IO_PORTS_8(PTH)) & 0xC0; frdupin@54: frdupin@54: // Uncomment to have a fixed baudrate of 250 kbps frdupin@54: //baudrate = 1; frdupin@54: etisserant@0: switch (baudrate) { frdupin@54: case 0x40: etisserant@0: bi0.clk = CAN_Baudrates[CAN_BAUDRATE_250K]; etisserant@0: MSG_WAR(0x3F30, "CAN 250 kbps ", 0); etisserant@0: break; frdupin@54: case 0x80: etisserant@0: bi0.clk = CAN_Baudrates[CAN_BAUDRATE_500K]; etisserant@0: MSG_WAR(0x3F31, "CAN 500 kbps ", 0); etisserant@0: break; frdupin@54: case 0xC0: etisserant@0: bi0.clk = CAN_Baudrates[CAN_BAUDRATE_1M]; etisserant@0: MSG_WAR(0x3F31, "CAN 1000 kbps ", 0); etisserant@0: break; etisserant@0: default: frdupin@80: bi0.clk = CAN_Baudrates[CAN_BAUDRATE_250K]; frdupin@54: MSG_WAR(0x2F32, "CAN BAUD RATE NOT DEFINED => 250 kbps ", 0); etisserant@0: } etisserant@0: frdupin@54: frdupin@54: frdupin@54: MSG_WAR(0x3F33, "SYNC signal generator ", 0); etisserant@0: etisserant@0: canInit(CANOPEN_LINE_NUMBER_USED, bi0); //initialize filters... etisserant@0: initTimer(); // Init hcs12 timer used by CanFestival. (see timerhw.c) etisserant@0: unlock(); // Allow interruptions etisserant@0: } etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ etisserant@0: // FUNCTIONS WHICH ARE PART OF CANFESTIVAL and *must* be implemented here. etisserant@0: etisserant@0: //------------------------------------------------------------------------------ etisserant@378: void gene_SYNC_heartbeatError(CO_Data* d, UNS8 heartbeatID ) etisserant@0: { etisserant@0: etisserant@0: MSG_ERR(0x1F00, "HeartBeat not received from node : ", heartbeatID); etisserant@0: } etisserant@0: etisserant@0: //------------------------------------------------------------------------------ etisserant@378: void gene_SYNC_initialisation(CO_Data* d) etisserant@0: { etisserant@0: MSG_WAR (0x3F00, "Entering in INIT ", 0); frdupin@54: initSensor(); frdupin@54: etisserant@0: IO_PORTS_8(PORTB) &= ~ 0x01; // led 0 : ON etisserant@0: IO_PORTS_8(PORTB) |= 0x0E; // leds 1, 2, 3 : OFF frdupin@54: etisserant@0: } etisserant@0: etisserant@0: etisserant@0: //------------------------------------------------------------------------------ etisserant@378: void gene_SYNC_preOperational(CO_Data* d) etisserant@0: { etisserant@0: MSG_WAR (0x3F01, "Entering in PRE-OPERATIONAL ", 0); etisserant@0: IO_PORTS_8(PORTB) &= ~ 0x03; // leds 0, 1 : ON etisserant@0: IO_PORTS_8(PORTB) |= 0x0C; // leds 2, 3 : OFF frdupin@54: /* default values for the msg CAN filters */ frdupin@54: /* Accept all */ frdupin@54: { frdupin@54: canBusFilterInit filterConfiguration = frdupin@54: { frdupin@54: 0x01, /* Filter on 16 bits. See Motorola Block Guide V02.14 */ frdupin@54: /*canidarx, canidmrx */ frdupin@54: 0x00, 0xFF, /* filter 0 */ frdupin@54: 0x00, 0xFF, /* filter 0 */ frdupin@54: 0x00, 0xFF, /* filter 1 */ frdupin@54: 0x00, 0xFF, /* filter 1 */ frdupin@54: 0x00, 0xFF, /* filter 2 */ frdupin@54: 0x00, 0xFF, /* filter 2 */ frdupin@54: 0x00, 0xFF, /* filter 3 */ frdupin@54: 0x00, 0xFF, /* filter 3 */ frdupin@54: }; frdupin@54: canChangeFilter(CANOPEN_LINE_NUMBER_USED, filterConfiguration); frdupin@54: } frdupin@54: // Reset the automatic change by SDO frdupin@54: applyDownloadedFilters = 0; frdupin@54: etisserant@0: } etisserant@0: etisserant@0: etisserant@0: //------------------------------------------------------------------------------ etisserant@378: void gene_SYNC_operational(CO_Data* d) etisserant@0: { etisserant@0: MSG_WAR (0x3F02, "Entering in OPERATIONAL ", 0); etisserant@0: IO_PORTS_8(PORTB) &= ~ 0x07; // leds 0, 1, 2 : ON etisserant@0: IO_PORTS_8(PORTB) |= 0x08; // leds 3 : OFF frdupin@54: frdupin@54: // Filtering the CAN received msgs. frdupin@54: // 2 ways frdupin@54: // First :applying an automatic filter frdupin@54: // Second : The values of the filtering registers are mapped in the object dictionary, frdupin@54: // So that a filtering configuration can be downloaded by SDO in pre-operational mode frdupin@54: frdupin@54: if (applyDownloadedFilters == 0) {// No downloaded configuration to apply frdupin@54: UNS16 accept1 = 0x0000; // Accept NMT frdupin@54: UNS16 mask1 = 0x0FFF; // Mask NMT frdupin@54: UNS16 accept2 = 0xE000; // Accept NMT error control (heartbeat, nodeguard) frdupin@54: UNS16 mask2 = 0x0FFF; // Mask NMT error control (heartbeat, nodeguard) frdupin@54: frdupin@54: canBusFilterInit filterConfiguration = frdupin@54: {// filters 3 and 4 not used, so configured like filter 1. frdupin@54: 0x01, /* Filter on 16 bits. See Motorola Block Guide V02.14 */ frdupin@54: /*canidarx, canidmrx */ frdupin@54: (UNS8)(accept1 >> 8), (UNS8)(mask1 >> 8), /* filter 1 id10...3*/ frdupin@54: (UNS8)accept1 , (UNS8)mask1, /* filter 1 id2 ... */ frdupin@54: (UNS8)(accept2 >> 8), (UNS8)(mask2 >> 8), /* filter 2 id10...3*/ frdupin@54: (UNS8)accept2 , (UNS8)mask2, /* filter 2 id2 ... */ frdupin@54: (UNS8)(accept1 >> 8), (UNS8)(mask1 >> 8), /* filter 3 id10...3*/ frdupin@54: (UNS8)accept1 , (UNS8)mask1, /* filter 3 id2 ... */ frdupin@54: (UNS8)(accept1 >> 8), (UNS8)(mask1 >> 8), /* filter 4 id10...3*/ frdupin@54: (UNS8)accept1 , (UNS8)mask1 /* filter 4 id2 ... */ frdupin@54: }; frdupin@54: canChangeFilter(CANOPEN_LINE_NUMBER_USED, filterConfiguration); frdupin@54: MSG_WAR (0x3F03, "Internal CAN Rcv filter applied ", 0); frdupin@54: } frdupin@54: else { // Apply filters downnloaded frdupin@54: canBusFilterInit filterConfiguration = frdupin@54: {// filters 3 and 4 not used, so configured like filter 1. frdupin@54: 0x01, /* Filter on 16 bits. See Motorola Block Guide V02.14 */ frdupin@54: /*canidarx, canidmrx */ frdupin@54: (UNS8)( acceptanceFilter1>> 8), (UNS8)(mask1 >> 8), /* filter 1 id10...3*/ frdupin@54: (UNS8)acceptanceFilter1 , (UNS8)mask1, /* filter 1 id2 ... */ frdupin@54: (UNS8)(acceptanceFilter2 >> 8), (UNS8)(mask2 >> 8), /* filter 2 id10...3*/ frdupin@54: (UNS8)acceptanceFilter2 , (UNS8)mask2, /* filter 2 id2 ... */ frdupin@54: (UNS8)(acceptanceFilter3 >> 8), (UNS8)(mask3 >> 8), /* filter 3 id10...3*/ frdupin@54: (UNS8)acceptanceFilter3 , (UNS8)mask3, /* filter 3 id2 ... */ frdupin@54: (UNS8)(acceptanceFilter4 >> 8), (UNS8)(mask4 >> 8), /* filter 4 id10...3*/ frdupin@54: (UNS8)acceptanceFilter4 , (UNS8)mask4 /* filter 4 id2 ... */ frdupin@54: }; frdupin@54: canChangeFilter(CANOPEN_LINE_NUMBER_USED, filterConfiguration); frdupin@54: MSG_WAR (0x3F04, "Downloaded CAN Rcv filter applied ", 0); frdupin@54: } etisserant@0: } etisserant@0: etisserant@0: //------------------------------------------------------------------------------ etisserant@378: void gene_SYNC_stopped(CO_Data* d) etisserant@0: { etisserant@0: MSG_WAR (0x3F02, "Entering in STOPPED ", 0); frdupin@54: IO_PORTS_8(PORTB) |= 0x0E; // leds 1, 2, 3, 4 : OFF etisserant@0: } etisserant@0: etisserant@0: // End functions which are part of Canfestival etisserant@0: //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ etisserant@0: etisserant@0: etisserant@0: /******************************************************************************/ etisserant@0: /********************************* MAIN ***************************************/ etisserant@0: /******************************************************************************/ etisserant@0: etisserant@0: etisserant@0: UNS8 main (void) etisserant@0: { etisserant@0: frdupin@54: MSG_WAR(0x3F34, "Entering in the main ", 0); etisserant@0: //----------------------------- INITIALISATION -------------------------------- etisserant@149: gene_SYNC_Data.heartbeatError = gene_SYNC_heartbeatError; etisserant@149: gene_SYNC_Data.initialisation = gene_SYNC_initialisation; etisserant@149: gene_SYNC_Data.preOperational = gene_SYNC_preOperational; etisserant@149: gene_SYNC_Data.preOperational = gene_SYNC_operational; etisserant@149: gene_SYNC_Data.stopped = gene_SYNC_stopped; etisserant@149: frdupin@54: etisserant@0: /* Put the node in Initialisation mode */ frdupin@54: MSG_WAR(0x3F35, "Will entering in INIT ", 0); etisserant@0: setState(&gene_SYNC_Data, Initialisation); etisserant@0: etisserant@0: //----------------------------- START ----------------------------------------- etisserant@0: /* Put the node in pre-operational mode */ etisserant@0: //MSG_WAR(0x3F36, "va passer en pre-op", 0); etisserant@0: //setState(&gene_SYNC_Data, Pre_operational); etisserant@0: frdupin@54: // Loop of receiving messages frdupin@54: while (1) { etisserant@0: Message m; etisserant@0: if (f_can_receive(0, &m)) { etisserant@365: //MSG_WAR(0x3F36, "Msg received", m.cob_id); frdupin@56: lock(); // Not to have interruptions by timer, which can corrupt the data etisserant@0: canDispatch(&gene_SYNC_Data, &m); frdupin@56: unlock(); frdupin@54: } frdupin@54: } etisserant@0: etisserant@0: return (0); etisserant@0: } etisserant@0: etisserant@0: etisserant@0: