Hi,
I'm trying to use GPIO128 through GPIO135 (names later changed to GPIO192 through GPIO199?), but I keep having problems with bit 1 of that port. I can't clear that bit out of GPEDAT once it is set. See image below. I just ran the line that set GPEDAT to 0x2 and that worked, and then I ran the line that should have made it 0x4, but instead, it is 0x6.
By the way, it seems likely that this type of problem is caused by incorrect configuration of the GPIO pins on the M3 side. But I'm assuming that isn't the case since these GPIO pins appear to be controlled only by the C28.
Thanks
Joel,
for GPIO128-135, Master subsystem doesn;t have to do any configuration. It is enough if it is out of reset. These GPIOs are controlled by Controlsubsystem only.
I repeated the same steps as you did and I don't see the problem. Can you repeat the test after an XRSn? Also can you step through the assembly and make sure if your code is not getting optimized in a way you don't want it to be?
One more thing you could try is directly write to the registers in a watch window or memory window and see if you can repeat the problem.
Best Regards
Santosh
Thanks for the reply.
I powered off my board, reset the emulator, exited CodeComposer, etc. and then ran the code again. The problem was gone. But then if I let it run the rest of my program, the problem comes back. Bit 1 of GPEDAT is stuck on.
At that point, if I do a software reset and reload the program, or just hit the "restart" button, when I get back to those same lines of code that I showed in my earlier post, writing a 1 to the data register causes it to be 3. Writing 2 causes the data register to be 2. Writing 4 to the data register causes it to be 6.
Writing directly to the registers in the watch window doesn't work either. If GPEDAT is 6 and I type in 0, the value becomes 2. If I put a 2 in the GPECLEAR register nothing happens to GPEDAT.
So I know something is happening when the rest of my program runs. But I have no idea what my code could be doing to make this happen. I know my program has a lot of IO reads and writes on these pins. But how would that cause a bit to get stuck?
Thanks,Joel
it could be that the IO is being accidentally configured back as input in your code, check the DIR register value for the IO at this point.
see if you can send your main file....
I have learned that the only way to clear the "stuck bit" is to power off my board. Hardware reset doesn't even work.
I also tried a different piece of code. I now have this in main()...-----------------------------------------------------
void main(void) { InitSysCtrl(); IOWrite(1,1); IOWrite(1,2); IOWrite(1,4);------------------------------------------------------------------------
And this is what the IOWrite function looks like....
-----------------------------------------------------------------------------
#pragma CODE_SECTION(IOWrite, "ramfuncs"); void IOWrite(ulong Mask, ulong NewValue)
{ int Temp;
IO_DIR = 0xFF;
if (Mask & 0x0000FF) { /* Put the 8 bits of data on the IO port pins */ IO_PORT = NewValue & 0x0000FF; IO_WRITE = 1;
ShortDelay
IO_BANK0 = 1; /* Sends clock pulse to latch when IOWRITE and bank select are both true */ }
* * * *
ShortDelay /* Wait for latch */ IO_WRITE = 0; /* Turn off all controls */ ShortDelay IO_BANK0 = 0; }----------------------------------------------------------------------
Here are the defines used in the above code...
#define ShortDelay asm(" nop"); asm(" nop"); asm(" nop"); asm(" nop"); asm(" nop"); asm(" nop");
#define IO_PORT GpioG2DataRegs.GPEDAT.all /* 8 bit I/O "data bus" is on group 2 GPIO pins (GPIO128 - GPIO135) */#define IO_DIR GpioG2CtrlRegs.GPEDIR.all /* If IO_DIR is set to one, the I/O port is for writing, 0 = reading */#define IO_BANK0 GpioG1DataRegs.GPADAT.bit.GPIO31 /* I/O port Bank 0 select (active high) is on PE7 (GPIO31) */#define IO_WRITE GpioG1DataRegs.GPBDAT.bit.GPIO35 /* = True to write to the 74HC273 selected by the bank selects above. PF3 (GPIO35) */
--------------------------------------------------------------------------
NOTE: The "ShortDelay" was added after I saw some strange behavior after successive writes to GPIO registers. I added that delay a couple of weeks ago and thought I had fixed all the GPIO problems, but I guess not.
When I run through main(), the first IOWrite() call makes GPEDAT = 1, the second call makes GPEDAT = 2, and the last one makes it 6 when it should be 4. Keep in mind that the following worked instead of IOWrite function calls....
GpioG2DataRegs.GPEDAT.all = 0x2; DELAY_US(100); GpioG2DataRegs.GPEDAT.all = 0x4;
As for the DIR bits, I do have a function that reads these IO pins, so I commented it out to make sure the DIR bits never change. That didn't help. Also, when the bit in GPEDAT was "stuck" I went to the watch window and verified the DIR bits were still 0xFF. They were. Then I tried changing the value of the DIR register to 0 and then back to 0xFF. The values changed correctly, but had no affect on GPEDAT being stuck.
What do you mean by below? if you use the highlighted portion below instead of the IOWrite calls, it works?
Joel Clasquin When I run through main(), the first IOWrite() call makes GPEDAT = 1, the second call makes GPEDAT = 2, and the last one makes it 6 when it should be 4. Keep in mind that the following worked instead of IOWrite function calls.... GpioG2DataRegs.GPEDAT.all = 0x2;DELAY_US(100);GpioG2DataRegs.GPEDAT.all = 0x4;
GpioG2DataRegs.GPEDAT.all = 0x2;DELAY_US(100);GpioG2DataRegs.GPEDAT.all = 0x4;
are you running the test on Control card?
santosh
Santosh,
That's correct. My code looks like this...
//#pragma CODE_SECTION(main, "ramfuncs");void main(void) { InitSysCtrl(); IOWrite(1,1); IOWrite(1,2); IOWrite(1,4);
GpioG2DataRegs.GPEDAT.all = 0x1; DELAY_US(100); GpioG2DataRegs.GPEDAT.all = 0x2; DELAY_US(100); GpioG2DataRegs.GPEDAT.all = 0x4;
--------------
First, I commented out the three IOWrite calls and stepped through the rest of the lines. GPEDAT changed to 1, 2, and then 4.
Then I un-commented the IOWrite calls and stepped through. GPEDAT changed to 1, 2, and then 6.
This is not a ControlCard. This is my board.
A few notes: I've tried to two different prototype boards and they both do the same thing. I've tried two different emulators (one is an XDS510 and the other is XDS100). I powered off the board between the two tests mentioned above and restarted everything the same way, with one exception. When I commented out the IOWrite function I had to manually type 0xFF into the GPEDIR register since that only happens in the IOWrite function.
I'm really stuck. Your help is appreciated.
FYI - I just realized that I didn't have EALLOW before writing IO_DIR = 0xFF in the IOWrite function.
Unfortunately, adding that didn't fix the problem.
are you setting IODIR for GPIO35 and GPIO31 anywhere in your code? I see that your are toggling them in your IO_WRITE and IO_BANK0 macros?
can you do a quick test for me on your board?
in your main....shown below, comment out the highlighted functions and add lines shown in green
void main(void) {InitSysCtrl();IOWrite(1,1);IOWrite(1,2);IOWrite(1,4);
GpioG1DataRegs.GPADAT.bit.GPIO31 = 1
GpioG1DataRegs.GPBDAT.bit.GPIO35 = 1
GpioG1DataRegs.GPADAT.bit.GPIO31 = 0
GpioG1DataRegs.GPBDAT.bit.GPIO35 = 0
GpioG2DataRegs.GPEDAT.all = 0x1;DELAY_US(100);GpioG2DataRegs.GPEDAT.all = 0x2;DELAY_US(100);GpioG2DataRegs.GPEDAT.all = 0x4;
after you do the above, if your problem comes back...see which one is causing the error, GPIO35 or GPIO31.
Thanks for sticking with this.
I think we're on the right track. I added the code as you suggested. GPIO35 is definitely the problem.
Yes, I am setting the DIR for GPIO35 and GPIO31. The InitSysCtrl function calls InitGPIO. Here's that function...
----------------------------------------
void InitGPIO(){ EALLOW; // Configure GPIO pins to function as such GpioG2CtrlRegs.GPEMUX1.all = 0x0000; // GPIO functionality GPIO128-135 (I/O port "data bus") GpioG2CtrlRegs.GPEDIR.all = 0; // Set the direction of the data bus to "read" initiially. This will change when reading or writing. GpioG1CtrlRegs.GPAMUX2.bit.GPIO29 = 0; // GPIO29 and 30 are for analog mux channel selection GpioG1CtrlRegs.GPAMUX2.bit.GPIO30 = 0; GpioG1CtrlRegs.GPAMUX2.bit.GPIO31 = 0; // GPIO31 - 33 are I/O bank select bits GpioG1CtrlRegs.GPBMUX1.bit.GPIO32 = 0; GpioG1CtrlRegs.GPBMUX1.bit.GPIO33 = 0; GpioG1CtrlRegs.GPBMUX1.bit.GPIO34 = 0; // GPIO34 is IO_WRITE GpioG1CtrlRegs.GPBMUX1.bit.GPIO35 = 0; // GPIO35 is IO_READ
GpioG1CtrlRegs.GPADIR.bit.GPIO29 = 1; // All I/O bus control signals are write, not read. GpioG1CtrlRegs.GPADIR.bit.GPIO30 = 1; GpioG1CtrlRegs.GPADIR.bit.GPIO31 = 1; GpioG1CtrlRegs.GPBDIR.bit.GPIO32 = 1; GpioG1CtrlRegs.GPBDIR.bit.GPIO33 = 1; GpioG1CtrlRegs.GPBDIR.bit.GPIO34 = 1; GpioG1CtrlRegs.GPBDIR.bit.GPIO35 = 1; GpioG1DataRegs.GPADAT.all = 0; GpioG1DataRegs.GPBDAT.all = 0; // Disable all the mux select bits
EDIS;}
----------------------------------------------
When I run this line of code...GpioG1DataRegs.GPBDAT.bit.GPIO35 = 1
The GPBDAT register changes, but so does the GPEDAT register. See attached screen shot.
FYI - I changed the offending line of code a little bit. Everything works OK if I set GPIO35 using GPBSET.
Changed this line....GpioG1DataRegs.GPBDAT.bit.GPIO35 = 1; // This did NOT work
To this line....GpioG1DataRegs.GPBSET.bit.GPIO35; // This does work
Actually, it doesn't quite work. GPBSET doesn't cause a problem with GPEDAT, but also doesn't actually set the bit in GPBDAT. It seems to do nothing.
Now when you are using GPIO0 to GPIO63 on your control subsystem, you should take care of assigning them to C28x subsytem from M3. Master subsytem owns these GPIO by default, they have to be switch to Control subsytem by using respective CSEL register.
Please let me know if you are doing that, ahead of using GPIO35 in your C28x code.
I do switch control to the C28. I have tried three different methods in the M3 code. The first line below is what I originally had. It should switch GPIO35 to the C28 core, right?
The second line is an attempt to switch the entire port. That didn't help.
The third method was copied from some example code I found. That didn't help. When I run the M3 program and then look at GPIO_PORTF - GPIOCSEL register in the watch window, it is equal to 0xFF.
-----------------------------------------------------
//GPIOPinConfigureCoreSelect(GPIO_PORTF_BASE, 0x4F, GPIO_PIN_C_CORE_SELECT); // Pins 0, 1, 2, 3 and 6. //GPIOPinConfigureCoreSelect(GPIO_PORTF_BASE, 0xFF, GPIO_PIN_C_CORE_SELECT);
HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY_DD; HWREG(GPIO_PORTF_BASE + GPIO_O_CR) |= 0x0000FF; for (i=0; i<20; i++){} HWREG(GPIO_PORTF_BASE+ GPIO_O_CSEL) = 0xFF;
I just realized a mistake I made when I started using the GPBSET register. I simply wasn't setting it equal to 1. Now the following line of code does work...
GpioG1DataRegs.GPBSET.bit.GPIO35 = 1;
So, it seems like the only problem is that I can't use this...
GpioG1DataRegs.GPBDAT.bit.GPIO35 = 1;
That line still appears to corrupt the GPEDAT register.
But at least I have a workaround.
Thanks a lot, Joel