-
Notifications
You must be signed in to change notification settings - Fork 7.6k
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
Looking for help modifing registers for GPIO (IDFGH-14010) #14833
Comments
Does the gpio_output_disable need to be set? I'm not sure if that prevents me from checking pin status or not? I need to do a setting gpio_output_disable on the pins seems to allow the external resister to and device to pull on the pins but I can not check the status now. |
S2 TRM link: https://www.espressif.com/sites/default/files/documentation/esp32-s2_technical_reference_manual_en.pdf ESP-IDF Programming Guide is mainly for those uses our peripheral driver APIs. Since you want to work with registers directly, I would say TRM is your reference. The 'n' and 'x' both correspond to the gpio number. You should first configure the pin as a simple input, and then also configure it as a simple output, following the guide stated in the TRM. BTW, you sure you don't want to try our upper GPIO driver APIs, but play around with the registers? :) |
"BTW, you sure you don't want to try our upper GPIO driver APIs, but play around with the registers? :)" so if I got this right and want to out GPIO1 as high I do this GPIO_FUNC1_OUT_SEL_CFG_REG ( 256 ) //n in this case is 1, use 256 for peripheral |
so I as playing around with a few registers and I found the issue I had was my GPIO bundles. Apparently once you set those up, you can not use the ports as input. Also the register modification are not as precise as the bundle code, nor is it as fast. I'm wondering if I can set up input bundles? This is how I set them up dedic_gpio_bundle_handle_t createBundle( const int arr[], int size, bool makeBundle)
} I thought that was both input and output? Or maybe I need to know how to change direction? I use this to set my output pin states I think this will read states but how to change from output to input? You'd think GPIO.pin[p].pad_driver =0; was enough but that does not work in bundle mode. |
If you want to use Dedicated GPIO module, then it is a different story than using GPIO module to read/write the IOs. For configuring an IO to be used as a dedicated GPIO, you don't need to call |
for a test, I changed everything to open drain But in normal GPIO_MODE_INPUT_OUTPUT my transition are much much faster, however I can not find a way to get my input wire conditions? If I do a read, it just shows what I see on the wires. So its working but I need to tell the GPIO to stop pulling high or low on the wires so my device can operate. Externally I use a 1k so that should be strong enough. but in this mode my device is not able to send data over the wire. to read I can use but I still need a way to disable the external pulling, or at least stop what seems to be preventing my device from using the lines. dedic_gpio_bundle_read_inworks too |
@ulao Hi, I think just adjust your external resister to 100~300 ohm and have a try! 1k will work like To allow more than one node output on one wire correctly, operate as You set GPIO_MODE_INPUT_OUTPUT will config pin as Push_Pull, which let your device can't output. |
Hi thx, my external pullups are fixed ( they are part of another device ) I can not change them or change the values. but in my tests bitbaning the pins from the registers works just fine in GPIO_MODE_INPUT_OUTPUT mode. I guess I'm consed on the modes, is GPIO_MODE_INPUT_OUTPUT not what I want? Setting to GPIO_MODE_INPUT_OUTPUT I can output but I was not able to read pins, that only seems to work in GPIO_MODE_INPUT_OUTPUT_OD mode? |
@ulao I'm confiused, what you mean I mean decrase your external resister, so even if now you have a fixed internal pullup in other device, you can also parallio another resister do pullup, and change gpio mode to |
Sorry for any confusion will try to itemize here.
output to set pins input I just change from output to input and I can bitbang. But with the ESP, things are a bit more complicated. I get that the bundle code is needed to group my pairs for faster reaction, that is very understandable. I also understand GPIO_MODE_INPUT_OUTPUT is the best mode for output. But what is still unclear, is how to change the directional modes? It woudl seem by default that the mode is output and I can use the following to change the pin states. #define PIN_PULLUP(p) asm volatile ("ee.set_bit_gpio_out %0" : : "I"(p) : ); I have tested this and it works great. but I'm not sure how to change from output to input. I need to swtich relatively fast. So I can not delete my bundle and remake it. I tried modifying the REG_IO_MUX_BASE and READ_PERI_REG registers but that didnt work. I'm just very confused how the registers work in the ESP for GPIO. There must be a simple way to change the pin to inputs and use no pullups. I was able to do this on a stm32 platform once before but documentation was a bit more available. If that does not exist is there a way to change to OD mode without rebuilding the bundle? |
Wanted to bump this and see if my last post was any clearer in what I'm hoping to do . Does my question at least make sense? |
Regarding your "really fast" requirement, not sure which is your real requirement, realtime performance (responding to an event, or the toggling speed). To eliminate the effect of insufficient current of pull-ups, and avoid I suggest to try our driver on a hardware that does not have other devices connected, with OUTPUT mode instead of OD. Try to emulate a reasonable use case and see if the toggling speed meet your requirements. For example if you are running in a task without other interrupts, then you can just polling and toggling the GPIO in the task; if you rely on some interrupts, then you can respond to one GPIO interrupt to see how long it will take to respond (usually I'll assume the performance is around 100us max) If you find the performance is much faster than your hardware, the problem may be caused by your OD+pullup. Consider modifying the hardware. Otherwise we can try other solutions, for example raw registers or dedicated GPIO. |
To realize it, you can try setting it up with https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/gpio.html#_CPPv411gpio_configPK13gpio_config_t , and use gpio_set_level / gpio_get_level or their alternatives later.
This will disable the pullup and pulldown, enable the input and output as OD. To read, gpio_set_level(1) first, then read. Please note that due to the possible delay caused by the pullup, you may need to delay (esp_rom_delay_us) until the external pullup to pull the line to a reasonable level. To output, you can use gpio_set_level(0) or 1. If you want to make it faster, you can use the LL directly, for example GPIO LL for esp32: https://github.com/espressif/esp-idf/blob/master/components/hal/esp32/include/hal/gpio_ll.h#L515 I believe the normal GPIO is fast enough compared to the external pullup. Dedicated GPIO is more complicated and overkilling. Only when you see there is much difference when replacing the driver with LL or raw registers, you need to consider the dedicated GPIO solution. |
My "really fast" requirement is just that I need to change output pin states quickly. The bundle code gave me that ability. In some cases I will wait for pin.1 to fall, and then I need to set the states of pins 2,3,4,5,6 etc. Much like a multiplexor. I'm currently at the stage where my external hardware is absent. My confusion is with code not hardware. I'm just trying to write some code logic that puts the esp32 into a output state, and change to input state. I can not use the built in functions because It takes a few hundred microseconds. That is too late. When I configure the bundle code for output I can do what I need as show above with the ee.set_bit_gpio_out regsiters. But to go to input mode, I can not delete my bundle and remake it. I was hoping to use registers to do that. like with AVR I can do output input So my current question or confusion, is how to change the pin state mode without rebuilding the bundle. UPDATE: I just saw the second reply, To read, gpio_set_level(1) first, then read. Please note that due to the possible delay caused by the pullup, you may need to delay (esp_rom_delay_us) until the external pullup to pull the line to a reasonable level. so you saying do not change from input to output, just use OD mode exclusively? |
I tried using the functions, but I'd rather just use registers. Is there a way to set w1ts.val ? maybe I tried
with a small pull up on the line, and it remains low. This is how I set up my bundle.
if I configure as output and use it works fine. So I know the hardware, scope, and probs are all correct. I can see the pin go high when I start uploading the code, but when its loaded, it holds it low. Should setting the pin level not pull and release the line allowing the pull up to take over? I left my dedicated bundles in place because previously when I started the project, it took far too long to respond. previous thread on that Oh I have flags on my bundle too. .flags = { |
My original plan is to get rid of the complicated dedicted gpio. If you have called initialization of dedicated GPIO somewhere, the GPIO registers (w1ts/w1tc) won't work because the output is controlled by dedicated GPIO. Maybe the OD will also fail to take effect. Please try with GPIO driver only. |
ah ok, no problem. This was much slower, I won't be able to use the device that way. I think using registers gets me closer to 200ns becauswe these gpio_set_level function take up lots of extra clocks to check thing. , but Hopeing to do better. I will need to loop a condition of a wire state and then set the condition of another. I only have 300ns to do it in. I know the esp32 clock cycles are closer to 10- 12ns and I also know there will be over head because of other things running, so the faster the better. With bundles I got near that speed but can not figure out how to do the open drain. |
@ulao I guess I finally get your problem. Please try to configure the IO with dedicate GPIO driver first with both
|
Ok sounds good. Thx for helping! Running in to some confusion. I'm only able to output on one pin, and its not the pin I'm write to. So before I try a read, I want to figure out the confusion. how I set up my bundle dedic_gpio_bundle_handle_t bundles[8];
} to enable output on all 4 I use this for a test I loop this ( I know the nameing is bad here, its just test code) { PIN_PULLDOWN(1 << 1);_delay_us(200); PIN_PULLDOWN(1 << 2);_delay_us(300); PIN_PULLDOWN(1 << 3);_delay_us(400); Then on my scope the only pin that works is GPIO00 and it does down for 400us. So
I suspect something in my group is set wrong but I'm not seeing it. I know what pins my scope is on, and its pin 0 that drops low for 400us, I'm sure of it, but unclear why. ----update------- I did test each bit with that API and only 0x08 has an effect. |
Please don't mix GPIO driver API with the dedicated GPIO driver API. Configure the IOs with dedicated GPIO driver:
Output:
Input:
|
ok all exmaples I saw on this matter used the gpio_config(), That maybe part of my issue then I will remove all of that code and try these exmaples . |
That works but the pin config is not correct. I noticed pin 3 does not work, 0,1,2 do. 3 is always low. bundle notices 0 is skipped... const int a[] = {1,2,3,4}; code whether its out is enabled or not, it does not work. in input mode its always low, even if I do the above. The other pins work fine. now interestingly this does not work at all, only GPIO0 seems to respond. for some reason I need to skip GPIO0 I did some testing. Is that not how bundles work? My size is dynamic ( see above ) also when using the 1,2,3,4 I can do this but can not use bits that does notwork right. more testing with 1,2,3,4 only 0 and 1 work. bits 0 and 1 fail to do anything. //GPIO0 //GPIO1 but this works for all, why is this so confusing? |
Which chip are you using...? I tried the following code on S2 and S3, and checked with the logic analyzer, all four pins (IO0, IO1, IO2, IO3) work fine.
And All works as expected. |
s3 yeah. so using 0,1,2,3 and your code. 1) tested with mask F and pins 0xf while (1) { result 2) test with mask F and pins 0x01 while (1) { result same result with 2) tested with mask F and pins 0x02 same result with 2) tested with mask F and pins 0x04 2) tested with mask F and pins 0x08 while (1) { result I figured I'd try a new board. I had one never opened, its doing the same thing. $ git status |
I could not reproduce. The dev board pins were not connect to any external device, right? Are you using the default sdkconfig, or is there anything special you selected in the menuconfig? |
External device, no its just the board. all of the code I wrote is in Start_LLAPI nothing outside ofthe above. I think the menu config is a viewer for the sdkconfig ? sdkconfig's are in every path so I figured may its the one at the root of my project? Its huge but will try to post it. I did a compare to a backup I had here is what is added here is the entire thing
|
Still not reproducible on my end. What else you can try is:
|
I think I just found my issue. WAs using the wrong varable. thx for the help at least the dedicate bundles work rirht. so full circle now ( back to Nov 12, 2024) . The original question cames back, why does the API / device force low? I need the external 1k pull-ups to keep the line high. Once I disable the output, I need it to release any pulling. Seem it wants to pull down. so do more testing the forcing of low is after I create the bundle before hand its not doing this. I create teh bundle when it starts up. |
Hmm, additional to what I said in #14833 (comment), after the configuration of the IOs with dedicated GPIO driver, please add the following code, and try again.
|
guessing you meana for use of input as that is the issue im having, let me try real fast here. |
yeah I think that did it? what did that do? |
|
ok, thx for the explination. All is working, I know this is off topic but one other issue I'm having is acurate delay timing. i.e #define _delay_us(a) do {uint64_t microseconds = esp_timer_get_time(); while (((uint64_t) esp_timer_get_time() - microseconds) < a) {}} while (0); I only get 3 us resolution here. I'd really like to do ; |
esp_rom_delay_us() is better than what you used, since it counts the cpu ticks internally. However, the best resolution is 1us. For any smaller time ticks, you may need to use 'nop'. |
ok yeah that worked out great. I will use NOP for nS btw: issue can be closed thx for the help. |
@songruo I made some test code PIN_PULLUP(LLAPI_DATA); _delay_us(2); and saw this. this means its 136 ns for the commands to change the pin state. and the nop adds 8. Is that the best I can hope for? I could bypass one fucntion and call the dedic_gpio_cpu function but can I was hoping to get around 14ns by hitting a register. |
|
Answers checklist.
General issue report
I had to use the register to change my pin state because of my timing requirement. I have most of it working but I can not get the input to release the state of the pin.
my goal is something like
set to output so I can hold pins high or low
set to input so I can read the start of an external pin.
I got the output working and my input is not, these are my defines.
#define PINPULLUP(p) asm volatile ("ee.setbitgpioout %0" : : "I"(p) : );
#define PIN_PULLDOWN(p) __asm __volatile ("ee.clr_bit_gpio_out %0" : : "I"(p) : );
#define PIN_MODE_OUTPUT(p) do { GPIO.enable_w1ts = (uint32_t)(1 << p); WRITE_PERI_REG((REG_IO_MUX_BASE + ( (p+1) * 4) ), (READ_PERI_REG(REG_IO_MUX_BASE + ( (p+1) * 4))|(1<<9))); } while (0);
#define PIN_MODE_INPUT(p) do { GPIO.enable_w1tc = (uint32_t)(1 << p); WRITE_PERI_REG((REG_IO_MUX_BASE + ( (p+1) * 4) ), (READ_PERI_REG(REG_IO_MUX_BASE + ( (p+1) * 4)) & ~(1<<9))); } while (0);
to write a pin state I do this
PIN_MODE_OUTPUT(1<<1);
then I can use either PIN_PULLDOWN or PIN_PULLUP
This works
to read I do
PIN_MODE_INPUT(1<<1);
but my wires stay low. and my external resister can not pull up. did I miss something?
The text was updated successfully, but these errors were encountered: