I am having some issues when I am trying to switch the pins on the GPIO pins being used for CAN on the DSP. When the program boots up it we default for Can A to be pins 18/19. But when I give it the command to switch pins for Ecan it does not work. I want to know if I am missing something in the process of switching the GPIO pins. Any help would be greatly appreciated. Let me know If you need to see more of the code but below is the section I use to select the GPIO pins.
CanAValue can be 0 or 1.
void InitECanaGpio(Uint16 CanAValue){ EALLOW;switch (CanAValue){ case 0: //default setting /* Enable internal pull-up for the selected CAN pins */ // Pull-ups can be enabled or disabled by the user. // This will enable the pullups for the specified pins. // Comment out other unwanted lines. GpioCtrlRegs.GPAPUD.bit.GPIO18 = 0; // Enable pull-up for GPIO18 (CANRXA) GpioCtrlRegs.GPAPUD.bit.GPIO19 = 0; // Enable pull-up for GPIO19 (CANTXA) /* Set qualification for selected CAN pins to asynch only */ // Inputs are synchronized to SYSCLKOUT by default. // This will select asynch (no qualification) for the selected pins. GpioCtrlRegs.GPAQSEL2.bit.GPIO18 = 3; // Asynch qual for GPIO18 (CANRXA) /* Configure eCAN-A pins using GPIO regs*/ // This specifies which of the possible GPIO pins will be eCAN functional pins. GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 3; // Configure GPIO18 for CANRXA operation GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 3; // Configure GPIO19 for CANTXA operation GpioCtrlRegs.GPADIR.bit.GPIO19 = 1; //Configure CANTXA as output break; case 1: /* Enable internal pull-up for the selected CAN pins */ // Pull-ups can be enabled or disabled by the user. // This will enable the pullups for the specified pins. // Comment out other unwanted lines. GpioCtrlRegs.GPAPUD.bit.GPIO30 = 0; // Enable pull-up for GPIO30 (CANRXA) GpioCtrlRegs.GPAPUD.bit.GPIO31 = 0; // Enable pull-up for GPIO31 (CANTXA) /* Set qualification for selected CAN pins to asynch only */ // Inputs are synchronized to SYSCLKOUT by default. // This will select asynch (no qualification) for the selected pins. GpioCtrlRegs.GPAQSEL2.bit.GPIO30 = 3; // Asynch qual for GPIO30 (CANRXA) /* Configure eCAN-A pins using GPIO regs*/ // This specifies which of the possible GPIO pins will be eCAN functional pins. GpioCtrlRegs.GPAMUX2.bit.GPIO30 = 1; // Configure GPIO30 for CANRXA operation GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 1; // Configure GPIO31 for CANTXA operation GpioCtrlRegs.GPADIR.bit.GPIO31 = 1; //Configure CANTXA as output break;} EDIS;}
David,
Are you in fact taking the CAN peripheral off bus before you switch the GPIO it is trying to use? If not try setting the CCR bit and waiting until CCE is asserted before changing the GPIO. Then clear CCR once the GPIO switch is complete.
If you're already doing this, then I'm running out of ideas. Would you mind posting your project, or a testcase which shows this failing condition?
Trey
Trey German
C2000 Applications
How exactly do I take the CAN peripheral off the bus. I don't believe the CCR is touched in this part of the code. It is only mentioned in shadow function.
Exactly how I stated in the previous post. Write a 1 to teh CCR bit in the control register and poll on the CCE bit in the status register. Once CCE is set, do your GPIO switch. After you switch the GPIOs clear the CCR bit and resume CAN operations.
I still can't get it to work. Am I enabling the CCR correctly:
void InitECanbGpio(Uint16 CanBValue){ struct ECAN_REGS ECanbShadow; EALLOW;
ECanbShadow.CANMC.bit.CCR = 1 ; // Set CCR = 1 switch (CanBValue){
case 0: // Turn off other CAN pins GpioCtrlRegs.GPAMUX1.bit.GPIO8 = 0; // Configure GPIO08 for CANTXB operation GpioCtrlRegs.GPAMUX1.bit.GPIO10 = 0; // Configure GPIO10 for CANRXB operation GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 0; // Configure GPIO12 for CANTXB operation GpioCtrlRegs.GPAMUX1.bit.GPIO13 = 0; // Configure GPIO13 for CANRXB operation GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 0; // Configure GPIO20 for CANTXB operation GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 0; // Configure GPIO21 for CANRXB operation
//default GpioCtrlRegs.GPAPUD.bit.GPIO16 = 0; // Enable pull-up for GPIO16 (CANTXB) GpioCtrlRegs.GPAPUD.bit.GPIO17 = 0; // Enable pull-up for GPIO17 (CANRXB)
// Set qualification for selected CAN pins to asynch only // Inputs are synchronized to SYSCLKOUT by default. // This will select asynch (no qualification) for the selected pins. // Comment out other unwanted lines.
GpioCtrlRegs.GPAQSEL2.bit.GPIO17 = 3; // Asynch qual for GPIO17 (CANRXB)
// Configure eCAN-B pins using GPIO regs*/ // This specifies which of the possible GPIO pins will be eCAN functional pins.
GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 2; // Configure GPIO16 for CANTXB operation GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 2; // Configure GPIO17 for CANRXB operation GpioCtrlRegs.GPADIR.bit.GPIO16 = 1; //Configure CANTXB as output
break; case 1:
// Turn off other CAN pins GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 0; // Configure GPIO16 for CANTXB operation GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 0; // Configure GPIO17 for CANRXB operation GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 0; // Configure GPIO12 for CANTXB operation GpioCtrlRegs.GPAMUX1.bit.GPIO13 = 0; // Configure GPIO13 for CANRXB operation GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 0; // Configure GPIO20 for CANTXB operation GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 0; // Configure GPIO21 for CANRXB operation
GpioCtrlRegs.GPAPUD.bit.GPIO8 = 0; // Enable pull-up for GPIO08 (CANTXB) GpioCtrlRegs.GPAPUD.bit.GPIO10 = 0; // Enable pull-up for GPIO10 (CANRXB)
GpioCtrlRegs.GPAQSEL1.bit.GPIO10 = 3; // Asynch qual for GPIO10 (CANRXB)
GpioCtrlRegs.GPAMUX1.bit.GPIO8 = 2; // Configure GPIO08 for CANTXB operation GpioCtrlRegs.GPAMUX1.bit.GPIO10 = 2; // Configure GPIO10 for CANRXB operation GpioCtrlRegs.GPADIR.bit.GPIO8 = 1; //Configure CANTXB as output
break;
case 2:
// Turn off other CAN pins GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 0; // Configure GPIO16 for CANTXB operation GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 0; // Configure GPIO17 for CANRXB operation GpioCtrlRegs.GPAMUX1.bit.GPIO8 = 0; // Configure GPIO08 for CANTXB operation GpioCtrlRegs.GPAMUX1.bit.GPIO10 = 0; // Configure GPIO10 for CANRXB operation GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 0; // Configure GPIO20 for CANTXB operation GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 0; // Configure GPIO21 for CANRXB operation
GpioCtrlRegs.GPAPUD.bit.GPIO12 = 0; // Enable pull-up for GPIO12 (CANTXB) GpioCtrlRegs.GPAPUD.bit.GPIO13 = 0; // Enable pull-up for GPIO13 (CANRXB)
GpioCtrlRegs.GPAQSEL1.bit.GPIO13 = 3; // Asynch qual for GPIO13 (CANRXB)
// Configure eCAN-B pins using GPIO regs // This specifies which of the possible GPIO pins will be eCAN functional pins.
GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 2; // Configure GPIO12 for CANTXB operation GpioCtrlRegs.GPAMUX1.bit.GPIO13 = 2; // Configure GPIO13 for CANRXB operation GpioCtrlRegs.GPADIR.bit.GPIO12 = 1; //Configure CANTXB as output
case 3:
// Turn off other CAN pins GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 0; // Configure GPIO16 for CANTXB operation GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 0; // Configure GPIO17 for CANRXB operation GpioCtrlRegs.GPAMUX1.bit.GPIO8 = 0; // Configure GPIO08 for CANTXB operation GpioCtrlRegs.GPAMUX1.bit.GPIO10 = 0; // Configure GPIO10 for CANRXB operatio GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 0; // Configure GPIO12 for CANTXB operation GpioCtrlRegs.GPAMUX1.bit.GPIO13 = 0; // Configure GPIO13 for CANRXB operationn
GpioCtrlRegs.GPAPUD.bit.GPIO20 = 0; // Enable pull-up for GPIO20 (CANTXB) GpioCtrlRegs.GPAPUD.bit.GPIO21 = 0; // Enable pull-up for GPIO21 (CANRXB)
GpioCtrlRegs.GPAQSEL2.bit.GPIO21 = 3; // Asynch qual for GPIO21 (CANRXB)
GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 2; // Configure GPIO20 for CANTXB operation GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 2; // Configure GPIO21 for CANRXB operation GpioCtrlRegs.GPADIR.bit.GPIO20 = 1; //Configure CANTXB as output
break; }
ECanbShadow.CANMC.bit.CCR = 0 ; // Set CCR = 0 EDIS;}#endif // if DSP28_ECANB
No you are not. The shadow registers exist such that you can do bitwise operations on them and then copy them to the active registers. This prevents a read-modify-write operation which can cause problems with registers that change state when they are read or written.
Set or clear the CCR bit in the active registers.
Trey,
Can you please be more specific. I do not know how to set or clear the CCr bit in the active register. What do i need to reference?
The shadow registers are just a chunk of RAM which is linked to be an exact replica of the ECan register structure. They are not real register, just RAM locations. Writing to them alone will do nothing to the CAN module.
I assume you are using a 2834x device? If you look in common/source a the ECan.c file you'll see in the InitECana function where it makes a copy of the actual register into the shadow register, modifies a bit in the shadowed copy and then writes it back to the active register. You'll want to do something similar to this to set and clear the CCR bit. When you poll on the CCE bit in the status register you'll need to make sure you are looking at the actual register, NOT the shadow register.
Does that help?
That helps but I have no idea how to do any of that. I am also using the F28335? I see the area you were talking about but i don't know what exactly i'm looking for.
void InitECana(void) // Initialize eCAN-A module{/* Create a shadow register structure for the CAN control registers. This is needed, since only 32-bit access is allowed to these registers. 16-bit access to these registers could potentially corrupt the register contents or return false data. This is especially true while writing to/reading from a bit (or group of bits) among bits 16 - 31 */
struct ECAN_REGS ECanaShadow;
EALLOW; // EALLOW enables access to protected bits
/* Configure eCAN RX and TX pins for CAN operation using eCAN regs*/
ECanaShadow.CANTIOC.all = ECanaRegs.CANTIOC.all; ECanaShadow.CANTIOC.bit.TXFUNC = 1; ECanaRegs.CANTIOC.all = ECanaShadow.CANTIOC.all;
ECanaShadow.CANRIOC.all = ECanaRegs.CANRIOC.all; ECanaShadow.CANRIOC.bit.RXFUNC = 1; ECanaRegs.CANRIOC.all = ECanaShadow.CANRIOC.all;
/* Configure eCAN for HECC mode - (reqd to access mailboxes 16 thru 31) */ // HECC mode also enables time-stamping feature
ECanaShadow.CANMC.all = ECanaRegs.CANMC.all; ECanaShadow.CANMC.bit.SCB = 1; ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
/* Initialize all bits of 'Master Control Field' to zero */// Some bits of MSGCTRL register come up in an unknown state. For proper operation,// all bits (including reserved bits) of MSGCTRL must be initialized to zero
ECanaMboxes.MBOX0.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX1.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX2.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX3.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX4.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX5.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX6.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX7.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX8.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX9.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX10.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX11.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX12.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX13.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX14.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX15.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX16.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX17.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX18.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX19.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX20.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX21.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX22.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX23.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX24.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX25.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX26.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX27.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX28.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX29.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX30.MSGCTRL.all = 0x00000000; ECanaMboxes.MBOX31.MSGCTRL.all = 0x00000000;
// TAn, RMPn, GIFn bits are all zero upon reset and are cleared again// as a matter of precaution.
ECanaRegs.CANTA.all = 0xFFFFFFFF; /* Clear all TAn bits */
ECanaRegs.CANRMP.all = 0xFFFFFFFF; /* Clear all RMPn bits */
ECanaRegs.CANGIF0.all = 0xFFFFFFFF; /* Clear all interrupt flag bits */ ECanaRegs.CANGIF1.all = 0xFFFFFFFF;
/* Configure bit timing parameters for eCANA*/ ECanaShadow.CANMC.all = ECanaRegs.CANMC.all; ECanaShadow.CANMC.bit.CCR = 1 ; // Set CCR = 1 ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
ECanaShadow.CANES.all = ECanaRegs.CANES.all;
do { ECanaShadow.CANES.all = ECanaRegs.CANES.all; } while(ECanaShadow.CANES.bit.CCE != 1 ); // Wait for CCE bit to be set..
ECanaShadow.CANBTC.all = 0;
#if (CPU_FRQ_150MHZ) // CPU_FRQ_150MHz is defined in DSP2833x_Examples.h /* The following block for all 150 MHz SYSCLKOUT - default. Bit rate = 250kbps */ //ECanaShadow.CANBTC.bit.BRPREG = 19; //250kbps ECanaShadow.CANBTC.bit.BRPREG = 4; //1Mbps, as requested for rev 11 ECanaShadow.CANBTC.bit.TSEG2REG = 2; ECanaShadow.CANBTC.bit.TSEG1REG = 10; #endif #if (CPU_FRQ_100MHZ) // CPU_FRQ_100MHz is defined in DSP2833x_Examples.h /* The following block is only for 100 MHz SYSCLKOUT. Bit rate = 1 Mbps */ ECanaShadow.CANBTC.bit.BRPREG = 9; ECanaShadow.CANBTC.bit.TSEG2REG = 1; ECanaShadow.CANBTC.bit.TSEG1REG = 6; #endif
ECanaShadow.CANBTC.bit.SAM = 1; ECanaRegs.CANBTC.all = ECanaShadow.CANBTC.all;
ECanaShadow.CANMC.all = ECanaRegs.CANMC.all; ECanaShadow.CANMC.bit.CCR = 0 ; // Set CCR = 0 ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
do { ECanaShadow.CANES.all = ECanaRegs.CANES.all; } while(ECanaShadow.CANES.bit.CCE != 0 ); // Wait for CCE bit to be cleared..
/* Disable all Mailboxes */ ECanaRegs.CANME.all = 0; // Required before writing the MSGIDs
EDIS;}
Ok, let me explain some more. Look at this snippet of code:
The first thing you'll notice is that we declare a struct of type ECAN_REGS and it is named ECanaShadow. This is a struct which has the same layout as the ECAN registers, but it is sitting on the stack (since it was declared in a function) not on the actual peripheral memory.
Next thing to notice is the EALLOW which is required to write to protected registers. I'm not sure exactly which registers are protected in the CAN controller, but the user guide should have this information.
Finally, You see 3 lines that modify the CANTIOC register. The first line makes a copy of the actual register value into the shadow register (which remember is just located in normal RAM). The second line modifies the TXFUNC bit in the copy of the register in RAM (the Shadow register). The third line write the whole shadow register back into the actual peripheral register.
Long story short, when you set the CCR bit don't do it like this:
ECanbShadow.CANMC.bit.CCR = 1 ; // Set CCR = 1
Do it like this:
ECanbRegs.CANMC.bit.CCR = 1 ; // Set CCR = 1
Trey and other readers,
I know it has been sometime but I have kept at this problem. I am able to get the GPIOS to switch! YAY! It turns out that they were switching all along but you have to do something odd first. The code switches whether you set the CCR or not. But for some reason the GPIOs do not switch right off the bat. I have to send a command to the DSP to switch between the GPIOS I have defined first. So I have to switch between 08/10, 12/13, 16/17, and 20/21. Usually only one of these GPIOS is inhibiting the ports from switching. Here's an example of how it is working right now.
If I send the command to switch 8/10. The line will not go high. But if I call 12/13 and then 8/10 the line will switch. Some my question is why do I have to initilize a random GPIO before I can switch?
That's really odd. You should be able to switch without going to another pair of GPIOs first. If you post a copy of your project (or a stripped down project), I'd be happy to take a look at it.
Is there an easier way for me to just e-mail you the contents of the project?
Probably the easiest way is to just zip up the project and post it here to the forums.
I would feel more comfortable e-mailing this to you since I do not wish to post the entire project online for everyone to see.