This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

LM4F232H5QDF - CAN Problem with PORTN and PORTF

I have a LM4F232-Evalkit on my desk and spent some time to make CAN interace 0 work. My problem: I configured CAN0 for PORTN, PORTF and PORTB. Out of these configurations, only CAN0 on PORTB (B4/B5) is working. For configurations on PORTN (N0/N1) and PORTF (F0/F3) I am not able to receive any CAN frames and sending (TX) is working, only after I enabled the loopback configuration in the CAN controller. I use Stellarisware to configure GPIO-pins and CAN-interface.

This configuration is working (PORTB):

ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
ROM_CANIntEnable(CAN0_BASE, CAN_INT_MASTER|CAN_INT_ERROR|CAN_INT_STATUS);
ROM_GPIOPinConfigure(GPIO_PB4_CAN0RX);
ROM_GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_4);
ROM_GPIOPinConfigure(GPIO_PB5_CAN0TX);
ROM_GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_5);

ROM_CANInit(CAN0_BASE);
ROM_CANBitRateSet(CAN0_BASE, ROM_SysCtlClockGet(), get_bitrate());
ROM_CANIntEnable(CAN0_BASE, CAN_INT_MASTER|CAN_INT_ERROR|CAN_INT_STATUS);
ROM_CANEnable(CAN0_BASE);

This configuration is not working (PORTN):
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
ROM_CANIntEnable(CAN0_BASE, CAN_INT_MASTER|CAN_INT_ERROR|CAN_INT_STATUS);
ROM_GPIOPinConfigure(GPIO_PN0_CAN0RX);
ROM_GPIOPinTypeCAN(GPIO_PORTN_BASE, GPIO_PIN_0);
ROM_GPIOPinConfigure(GPIO_PN1_CAN0TX);
ROM_GPIOPinTypeCAN(GPIO_PORTN_BASE, GPIO_PIN_1);

ROM_CANInit(CAN0_BASE);
ROM_CANBitRateSet(CAN0_BASE, ROM_SysCtlClockGet(), get_bitrate());
ROM_CANIntEnable(CAN0_BASE, CAN_INT_MASTER|CAN_INT_ERROR|CAN_INT_STATUS);
HWREG(get_base_addr() + CAN_O_CTL) |= CAN_CTL_TEST;
HWREG(get_base_addr() + CAN_O_TST) |= CAN_TST_LBACK; // Enable loopback to see any TX messages on the bus
ROM_CANEnable(CAN0_BASE);

It seems to me that the RX-pin is not routed to the CAN0-interface internally. When I tried the PORTF configuration, I found out that the AFSEL register of PORTF was set to 0x8 instead of 0x9. When I tried to configure this register manually to 0x9 in my debugger (GDB) the value remained 0x8. When I entered 0xFF the value read back was 0xFE. Bit0 remains always 0. That would explain the behaviour of not receiving any data from the RX pin.

Question:  Is there an error on my side, or is this an internal MCU error? The  MCU on my eval board is a LM4F232H5QDIGA1 19AD23W G1. I've checked the errata (Rev. C), but found no related information.

  • Can quickly/easily resolve your Port "F" mystery.   PF0 is a "special" pin - defaults as NMI and thus requires a special, "unlocking" procedure to repurpose.  Believe that PD7 behaves/responds in the identical manner.  PF0/PD7 are covered in the GPIO section of the 1400+ page datasheet - takes some "digging" to absorb...

  • Thanks for resolving the F0 riddle. It's also in the errata - shame on me.

    I haven't tried to configure CAN0 for PORTE (E4/E5) as there is an accelerator sensor connected to those pins and I'm not ready to slaughter my evalkit, yet.

  • Norbert Melinat said:
    I'm not ready to slaughter my evalkit, yet.

    Well played, mon ami.  1400+ pgs does "dull" the mind - and who (really) reads errata?   Love your use of the operative word, "yet!"  Slaughter very much in the cards unless hyped new board (I recall only picture of a header - MCU nowhere in evidence/display) may suit your purpose.  Bon chance...

    Glanced quickly @ your code - don't like:

    ROM_CANIntEnable(CAN0_BASE, CAN_INT_MASTER|CAN_INT_ERROR|CAN_INT_STATUS);
    ROM_GPIOPinConfigure(GPIO_PB4_CAN0RX);

    Believe it bad form to enable the interrupt in advance of full/proper Port & Pin Set-Ups/Configs.  If I get time later I'll revisit your Port N issue - although as you have one port working you should be able to make that repair...

    Further - to reduce your "wear/tear" - you may mingle multiple pins w/in GPIOPinType - but not for GPIOPinConfigure!  (joy of inconsistency...)

    ROM_GPIOPinTypeCAN(GPIO_PORTN_BASE, GPIO_PIN_0);
    ROM_GPIOPinTypeCAN(GPIO_PORTN_BASE, GPIO_PIN_1);
    may be replaced by:
    ROM_GPIOPinTypeCAN(GPIO_PORTN_BASE, GPIO_PIN_0 | GPIO_PIN1);

  • Just noted the following after rapid-fire "read" of SW-DRL-UG:

    Also, if the same signal (i.e. CAN0RX)  is assigned to two different GPIO port pins, the signal is assigned to the port with the lowest letter and the assignment to the higher letter port is ignored.   Should your code have been compiled as listed (both Port B and Port N - and this we do not know) - this may explain.

    And - have you reviewed Eval Board schematic - to insure that no "other" board use of PN0 may cause conflict?

  • I tried different PORT configurations separately. I haven't tried to use PORTB and PORTN at the same time. PORTB configuration works, PORTN and PORTF don't. For PORTF I know now why (needs to be unlocked, first). I haven't tried PORTE, yet.

    Checked the board schematics, again. The board is the TI LM4F232 eval kit board. PORTN pins are directly routed to header pins on the side of the board, no other on-board peripherals to interfere with. I used an oscilloscope to verify that the TTL-RX/TX signals of the CAN-transceiver actually end up on  the N0/N1 pins of the MCU. They actually do, but somehow that RX-signal is not routed to the CAN peripheral inside. When I enable LOOPBACK mode I do see a TX-signal on N1. There's something wrong with the routing of N0. I also checked the PORTN GPIO register. Looks ok to me.

    Has anybody actually made CAN0 work on PORTN?

  • Not to overly beat this, "dead horse" but would you be good enough to detail just how you test/verified Port_B Can_RX operation?  If possible - I will try to duplicate your set-up - and then report.  Must say - your initial code post does not reveal Port_N to be fully "duplicative" of Port_B.  Would be most useful if you'd provide as exact a listing as possible to insure our optimal test agreement.

    Should you have earlier "tested" by "looping back" I suspect failure of the higher lettered CAN Ports is explained by my last post...  (test should have looped CAN0 to CAN1 !)

  • CAN-Setup: The MCU's CAN interface is connected to a TI-VP232 CAN Transceiver. The Transceiver is powered by the board's 3.3V Vcc line. The Transceiver CAN-H/L line is connected to the CAN-Bus. The CAN-Bus is made by two nodes: First node is the MCU/Transceiver combination, the second node is a Vector CANcaseXL device. The CAN-Bus is terminated by a 120Ohm Resistor. The Baudrate is 500kBit/s. The CANcaseXL device is connected to a PC running the Vector CANoe Application. I use this application to trace CAN activities and run a CAN-Restbus-Simulation that emulates some other ECU that send/receive messages to and from the MCU.

    My actual program code for CAN0/PORTB (works!) is

        template<>
        Stellaris_CAN_node<CAN0_BASE, GPIO_PORTB_BASE>::Stellaris_CAN_node(Timer& timer, CAN_transceiver* t, uint32_t btr)
        : Stellaris_CAN_node_base(CAN0_BASE, timer, t, btr)
        {
            if (! s_instance) {
                ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);
                ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
                ROM_GPIOPinConfigure(GPIO_PB4_CAN0RX);
                ROM_GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_4);
                ROM_GPIOPinConfigure(GPIO_PB5_CAN0TX);
                ROM_GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_5);
                Stellaris_CAN_node_base::reset();
                ROM_IntEnable(INT_CAN0);
                s_instance = this;
            } else {
                std::abort(); // Already instantiated
            }
        }

    The code for CAN0/PORTN (does not work) is:

        template<>
        Stellaris_CAN_node<CAN0_BASE, GPIO_PORTN_BASE>::Stellaris_CAN_node(Timer& timer, CAN_transceiver* t, uint32_t btr)
        : Stellaris_CAN_node_base(CAN0_BASE, timer, t, btr)
        {
            if (! s_instance) {
                ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);
                ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
                ROM_GPIOPinConfigure(GPIO_PN0_CAN0RX);
                ROM_GPIOPinTypeCAN(GPIO_PORTN_BASE, GPIO_PIN_0);
                ROM_GPIOPinConfigure(GPIO_PN1_CAN0TX);
                ROM_GPIOPinTypeCAN(GPIO_PORTN_BASE, GPIO_PIN_1);
                Stellaris_CAN_node_base::reset();

              HWREG(CAN0_BASE + CAN_O_CTL) |= CAN_CTL_TEST;
              HWREG(CAN0_BASE + CAN_O_TST) |= CAN_TST_LBACK; // Enable loopback to see any TX messages on the bus
                ROM_IntEnable(INT_CAN0);
                s_instance = this;
            } else {
                std::abort(); // Already instantiated
            }
        }

    The reset() function is the same for both cases and is:

        void Stellaris_CAN_node_base::reset(void) {
            ROM_CANInit(get_base_addr());
            ROM_CANBitRateSet(get_base_addr(), ROM_SysCtlClockGet(), get_bitrate());
            ROM_CANIntEnable(get_base_addr(), CAN_INT_MASTER|CAN_INT_ERROR|CAN_INT_STATUS);
            ROM_CANEnable(get_base_addr());
        }

    My personal theory on why the loopback trick is working, is that the CAN-Controller waits to detect a recessive state on the bus before sending any messages. Without a loopback the CAN-controller detects only a dominant state, that prevents any messages to send. With loopback enabled the CAN-Controller detects a recessive state and actually start to send messages on the bus. Then I see the messages on the bus. Anyway, even with loopback enabled, I do not receive any messages sent by other nodes on the BUS. Pin N0 does not seem to be connected internally to the CAN0 peripheral.

  • Norbert - thank you - very much appreciated.  (J'avais l'appreciation tres grande)  What a wonderfully crafted, caring post - will benefit many - simply outstanding! 

    For the sake of total completeness - would you be so good to add the "set-up/config" of failing Port "N"?  (suspect you've endless compared it with the successful Port "B".)

    You should know that multiple others have reported similar CAN issues with PN0.  (you may review via, "Forum Search" (upper left, atop this forum page - enter CAN PN0)  That said - respected, most capable vendor engineer reports, "all is well" w/PN0 from her/others internal testing.  Apparently there was an issue on older date code parts - but I believe yours to be newer - thus "fixed."

    While bothersome - you do have a rich assortment of CAN pins/ports - perhaps not, "End of the World" to switch to a different pin.  I suggest that you repurpose PN0 as GPIO. 

    And - "Save Best for Last Dept." - Do you realize that you are not "forced" to use the SAME PORT to harvest each/every of your chosen Peripheral's pins?  (Say What?)  For example - to maximize my harvesting of firm's 64 pin M4F - I freely mixed/matched pins from DIFFERENT PORTS - to achieve full Peripheral functionality - while far better achieving our project's diverse, multi-peripheral goals.  (which could not be achieved via, unimaginative, "strict Peripheral to Single/Common Port" pin harvesting/selection. 

    Truth in Advertising - I have attempted and verified proper operation - while employing such, "Multi-Port, Peripheral Pin Combination" via: SSI, UART, QEI, & I2C.  (have yet to use CAN)  So long as you replace PN0 with another pin designated as having "CAN0RX capability" - this should work - thus overcoming your issue.

    Again - thank you for great effort - certainly of high value to many...  (i.e. spirit of this forum)

  • Thank you for your spending your time on this issue. Thanks also for the tip with the multi-port-pin configuration. Personally, I have pulled a Stop-Loss on this issue and decided to go with Port B and so be it. I was seeking for an explanation on why certain port configurations do work and others don't. Taking other related forum posts into account, I come to the following conclusion:

    This is revision A1 of the LM4F232H5QD MCU. A couple of bugs of the A1 revision have been reported in the errata, some other have not. This is one of them.

    • CAN0 on PORTB - works
    • CAN0 on PORTN - does not work (probably silicon bug)
    • CAN0 on PORTF - does not work (even after rresolving the NMI issue, see related forum posts. Probably silicon bug)
    • CAN0 on PORTE - cannot verify (assumed to not work)

    I will reconsider to re-check this with newer revisions of the MCU once I can lay hand on some.

  • Norbert Melinat said:
    I have pulled a Stop-Loss on this issue

    That's probably wise - and too rarely seen this/other forums.  Business case should always intrude - too often is afterthought - firms/individuals thus suffer.

    Thanks your kindness - this reporter became aware of, "Peripheral satisfaction via multi-port, pin harvest" after close, repeated read of ARM (non MCU vendor specific) docs - and achieved/confirmed such capability - first on another vendor's ARM.  Few months later, "red garbed FAE's arrived" - I duly "asked" about this technique - silence - very limited vendor recognition - "no comment"...  thus "first such recognition" awards to famed, "NIH"!   (this is documented w/in multiple emails) 

    Such thoughtful, "Peripheral Pin Selection" is a powerful technique - can enable much smaller, lower cost MCUs to replace, "less crafted" larger ones.