Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cc2538/periph/gpio: workaround for old defines and some fixes #6773

Closed
wants to merge 6 commits into from

Conversation

AnonMall
Copy link

Temporary workaround for issue mentioned in #6650. Also some small fixes, as the interrupts haven't been working anymore. Enabling interrupts for PORT_D GPIO pins still causes my board to freeze, but interrupts are now working again for all other ports.

@AnonMall
Copy link
Author

Fixed some problems in clearing the interrupt register, causing the isr to never end. PORT_D interrupts also work now

@PeterKietzmann PeterKietzmann added Platform: ARM Platform: This PR/issue effects ARM-based platforms Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) Area: drivers Area: Device drivers labels Mar 28, 2017
#define PORTNUM_SHIFT (12U)
#define PIN_MASK (0x00000007)
#define MODE_NOTSUP (0xff)

static inline cc2538_gpio_t *gpio(gpio_t pin)
{
return (cc2538_gpio_t *)(pin & GPIO_MASK);
if(((uint32_t)pin &GPIO_MASK) == 0){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you explain a bit more why this handling is needed, and what error you see without this fix - and how to reproduce?!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now there are two types of pin encoding. The one provided by cpu/cc2538/include/cc2538-gpio.h and the one which is used here, provided by the RIOT gpio interface. The one in cc2538-gpio.h is also used for the pin name defines, which are then used for configuring boards, such as the Re-Mote. Because one encoding does not translate well into the other, SPI Pins for example, are not correctly initialized. The error can be reproduced by simply initializing pins through their pin-names, i.e. GPIO_PD4 and then setting or reading them. The result will be, that nothing happens, as the pin will not be propably addressed. This workaround just checks, whether the old or the new encoding is used. And if the old encoding is detected, it then translates it according to the new gpio interface pin encoding. As I mentioned, this should only be a temporary workaround. The fix would be to adjust cc2538-gpio.h pin encoding and all its functions. I have stated one example in the issue, linked to this pull request. I hope I was able to answer your questions adequately.
Cheers

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for clearing things up! So this if ... else is not really needed (and should be fixed otherwise), and the actual fix is correction of PORTNUM_MASK and the interrupt initialization?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing PORTNUM_MASK alone does not work unfortunately, as there is different use of both encodings. While the new one uses the upper bits of the encoding for the port address and the lower bits for the pin number, the old encoding style, as in the pin names, holds no information on which address to access and had to be calculated. So the usage of both is different. A more permanent fix would be to change cc2538-gpio.h and make in compatible with this implementation.

@@ -26,19 +26,27 @@
#include "periph/gpio.h"

#define GPIO_MASK (0xfffff000)
#define PORTNUM_MASK (0x00007000)
#define PORTNUM_MASK (0x00003000)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why changing this, I think 0x00007000 is right because PORT_D = 3 = b11 and base address of GPIO_A = 0x400d9000 = b1101 1001 0000 0000 hence

  b0000 0011 0000 0000 (=PORT_D << 12)
+ b1101 1001 0000 0000 (=GPIO_A)
= b1101 1100 0000 0000
          ^^ -> 0x00003000 (PORTNUM_MASK)

but with the old

= b1101 1100 0000 0000
         ^^^ -> 0x00007000 (PORTNUM_MASK)

the new portnum mask would not capture port_d, or does it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, you changed the calculation, too - so this still works. mhm, don't know if I like that.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just tested it. That fix seems to be a remnant of a previous fix, where the 'PORTNUM_MASK' would give me negative numbers, so I reworked it. But the calculation and the 'PORTNUM_MASK' can remain the same for me, as long as the if-clause is present, in order to work with the old encoding.

@@ -174,7 +182,7 @@ static inline void handle_isr(cc2538_gpio_t *gpio, int port_num)
{
uint32_t state = gpio->MIS;
gpio->IC = 0x000000ff;
gpio->IRQ_DETECT_ACK = 0x000000ff;
gpio->IRQ_DETECT_ACK = (0xff << (port_num * 8));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more consistent would even be

gpio->IRQ_DETECT_ACK = (0xff << (port_num * GPIO_BITS_PER_PORT));

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah you're right. That's better.

@smlng
Copy link
Member

smlng commented Jul 3, 2017

@AnonMall can you factor out your fix of int gpio_init_int and make it separate PR? Or, if you don't have time to work on this I can overtake that.

Regarding the other changes aka workaround: I'd rather work on completely fixing the GPIO stuff which means to rework I2C, SPI, and UART to the RIOT GPIO API, but it has to be (or should be) done anyway.

@AnonMall
Copy link
Author

AnonMall commented Jul 3, 2017

Just factored it and opened a new PR. #7303

@smlng
Copy link
Member

smlng commented Jul 7, 2017

@AnonMall please try if #7316 or #7320 (the latter includes the former + rework of all other periphs) resolve this issue #6650 for you and hence make this workaround obsolete.

@AnonMall
Copy link
Author

AnonMall commented Jul 7, 2017

@smlng #7320 seems to be working without problems for all periph related things direct gpio operations. But that also means that as long as we don't define them ourselves in our programs, we have to refrain from using pin names, am I right? Also just a small question, which might be more of a RIOT SPI API thing. There is currently no possibilty to use the spi bus chip select of, lets say for example SSI0, as a software chip select right? Because right now they are coded as hardware chip select (at least on the CC2538) with no option in changing that, what leads to the problem, when I want to do spi burst operations or try to access extended register addresses on devices.

@AnonMall AnonMall closed this Jul 7, 2017
@smlng
Copy link
Member

smlng commented Jul 7, 2017

SPI is not my strong suit maybe @haukepetersen can help here?

Anyhow, my currently open PRs for cc2538 are all about resolving the conflicting GPIO pin definitions and handling between RIOTs and TIs native GPIO API.

I would say open an issue for SPI, stating your use-case as outlined above - and then we'll see howto fix that in a separate PR.

But also, as you have been: thanks for testing!

@haukepetersen
Copy link
Contributor

Not sure I understand the question about the SPI CS pin usage correctly. You want to control the SPI CS line manually, is that it? In this case, you simply pass GPIO_UNDEF as cs parameter to the spi_write function, and voilla, you have full control over the CS line outside of the SPI driver.

And by the way, the cc2538`s SPI does currently not support the usage of hardware chip select lines...

@AnonMall
Copy link
Author

Sorry for the late reply. What I meant is, that while I still can use GPIO_UNDEF for spi_write, in the cpu/cc2538/periph/spi.c spi_init_pins(...) function, there is a chip select pin being programmed for hardware control, which is defined through the boards periph_conf.h. This may be only the case for the cc2538, as I haven't looked into other platforms, but this means, that I am not able to do any software chip select on that same pin, if I don't comment out, either the chip select pin in the periph_conf.h or spi.c. This is nescessary, as I have implemented a CC1200 driver, for which I am going to open a PR soon. The CC1200 has an extended register address set and the hardware controlled chip select is interfering with register access. Maybe I am missing something, for which I would be glad to be enlightend. I hope that I was able to explain my problem a bit more detailed. Thanks in advance.

@haukepetersen
Copy link
Contributor

Ah, I think I get it now. Actually, the spi driver code for the cc2538 is broken: the cs pin should never be touched when calling spi_init_pins(). That is what the spi_init_cs() function is explicitly for...

See #7389 for a fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: drivers Area: Device drivers Platform: ARM Platform: This PR/issue effects ARM-based platforms Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants