-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Conversation
Fixed some problems in clearing the interrupt register, causing the isr to never end. PORT_D interrupts also work now |
#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){ |
There was a problem hiding this comment.
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?!
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
cpu/cc2538/periph/gpio.c
Outdated
@@ -26,19 +26,27 @@ | |||
#include "periph/gpio.h" | |||
|
|||
#define GPIO_MASK (0xfffff000) | |||
#define PORTNUM_MASK (0x00007000) | |||
#define PORTNUM_MASK (0x00003000) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
cpu/cc2538/periph/gpio.c
Outdated
@@ -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)); |
There was a problem hiding this comment.
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));
There was a problem hiding this comment.
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.
@AnonMall can you factor out your fix of 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. |
Just factored it and opened a new PR. #7303 |
@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. |
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! |
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 And by the way, the cc2538`s SPI does currently not support the usage of hardware chip select lines... |
Sorry for the late reply. What I meant is, that while I still can use |
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 See #7389 for a fix. |
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.