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

Thank you so much for great lib, I cannot figure out I2C RD/WR. #66

Closed
sam0910 opened this issue Feb 8, 2022 · 8 comments
Closed

Thank you so much for great lib, I cannot figure out I2C RD/WR. #66

sam0910 opened this issue Feb 8, 2022 · 8 comments

Comments

@sam0910
Copy link

sam0910 commented Feb 8, 2022

Greetings!
Thank you for the great lib for micropython.
I could have done many things with your lib, controlling lcd brightness during deepsleep,
communicate with between ULP and main core. It is so great!

I've asked in micropython forum, But I cannot still firgure out hot to get the I2C RD/WR.

I've got some sensors which doesn't have interrupts, I would like to wirte and read a single byte.
Referring the ESP32 technical reference manual,
, intializing I2C connection, but it doesn't work.
Could you please help me to get there?

#define DR_REG_RTCIO_BASE            0x3ff48400
#define DR_REG_RTC_I2C_BASE          0x3ff48C00
#define DR_REG_SENS_BASE             0x3ff48800                  
#define SENS_SAR_SLAVE_ADDR1_REG     0x3FF4883C 
#define SENS_I2C_SLAVE_ADDR0         0x000007FF                  
#define SENS_I2C_SLAVE_ADDR0_S       11
#define SENS_I2C_SLAVE_ADDR1_S       0
#define RTC_IO_SAR_I2C_IO_REG        0x3FF484C4
#define RTC_IO_SAR_I2C_SDA_SEL_S     30
#define RTC_IO_SAR_I2C_SCL_SEL_S     28
#define RTC_I2C_SCL_LOW_PERIOD_REG   0x3FF48C00 
#define RTC_I2C_SCL_HIGH_PERIOD_REG  0x3FF48C38
#define RTC_I2C_SCL_LOW_PERIOD_S     0
#define RTC_I2C_SCL_HIGH_PERIOD_S    0
#define RTC_I2C_SDA_DUTY_REG         0x3FF48C30
#define RTC_I2C_SDA_DUTY_S           0
#define RTC_I2C_SCL_START_PERIOD_REG 0x3FF48C40
#define RTC_I2C_SCL_START_PERIOD_S   0
#define RTC_I2C_SCL_STOP_PERIOD_REG  0x3FF48C44
#define RTC_I2C_SCL_STOP_PERIOD_S    0
#define RTC_I2C_TIMEOUT_REG          0x3FF48C0C
#define RTC_I2C_TIMEOUT_S            0
#define RTC_I2C_CTRL_REG             0x3FF48C04
#define RTC_I2C_MS_MODE_S            4 
#define DR_REG_RTCIO_BASE            0x3ff48400
#define RTC_IO_TOUCH_PAD0_REG        0x3ff48494 
#define RTC_IO_TOUCH_PAD1_REG        0x3ff48498 
#define RTC_IO_TOUCH_PAD2_REG        0x3ff4849c 
#define RTC_IO_TOUCH_PAD3_REG        0x3ff484a0 
#define RTC_IO_TOUCH_PAD0_FUN_SEL_S  17 
#define RTC_IO_TOUCH_PAD1_FUN_SEL_S  17 

data:        .long 0
value:       .long 0

.global entry
entry:   
# Select SDA/SCL pins to version 1, TOUCH2 and TOUCH3 (version 0 is TOUCH0 and TOUCH1)
WRITE_RTC_REG(RTC_IO_SAR_I2C_IO_REG, RTC_IO_SAR_I2C_SDA_SEL_S, 2, 0)
WRITE_RTC_REG(RTC_IO_SAR_I2C_IO_REG, RTC_IO_SAR_I2C_SCL_SEL_S, 2, 0)
WRITE_RTC_REG(RTC_IO_TOUCH_PAD0_REG, RTC_IO_TOUCH_PAD0_FUN_SEL_S, 2, 3) 
WRITE_RTC_REG(RTC_IO_TOUCH_PAD1_REG, RTC_IO_TOUCH_PAD1_FUN_SEL_S, 2, 3) 

# WRITE_RTC_REG(rtc_reg, low_bit, bit_width, value)
WRITE_RTC_REG(SENS_SAR_SLAVE_ADDR1_REG, SENS_I2C_SLAVE_ADDR0_S, 11, 0x76)

# Set SCL speed to 100khz
WRITE_RTC_REG(RTC_I2C_SCL_LOW_PERIOD_REG, RTC_I2C_SCL_LOW_PERIOD_S, 19, 40)
WRITE_RTC_REG(RTC_I2C_SCL_HIGH_PERIOD_REG, RTC_I2C_SCL_HIGH_PERIOD_S, 20, 40)

# SDA duty (delay) cycles from falling edge of SCL when SDA changes.
WRITE_RTC_REG(RTC_I2C_SDA_DUTY_REG, RTC_I2C_SDA_DUTY_S, 20, 16)

# Number of cycles after start/stop condition
WRITE_RTC_REG(RTC_I2C_SCL_START_PERIOD_REG, RTC_I2C_SCL_START_PERIOD_S, 20, 30)
WRITE_RTC_REG(RTC_I2C_SCL_STOP_PERIOD_REG, RTC_I2C_SCL_STOP_PERIOD_S, 20, 44)

# cycles before timeout
WRITE_RTC_REG(RTC_I2C_TIMEOUT_REG, RTC_I2C_TIMEOUT_S, 20, 200)

# Set mode to master
WRITE_RTC_REG(RTC_I2C_CTRL_REG, RTC_I2C_MS_MODE_S, 1, 1)

I2C_RD  0xa2, 7, 0, 0
@ThomasWaldmann
Copy link
Collaborator

Sorry, but I can't help you with this. Although I started py-esp32-ulp, I did not practically use it much myself.

@wnienhaus
Copy link
Collaborator

I have not tried I2C from the ULP yet, so I can perhaps try to give some pointers, rather than a concrete answer.

Your code snippet looks like it might have been derived from this code https://github.com/wardjm/esp32-ulp-i2c/blob/master/ulp.s . Note that the Arduino code is doing some initialisations, that might be needed. From a quick glance it feels like the initialisations are basically a copy of what is in the ULP code, but maybe you can find something in the init code that is missing from the ULP code. Init code that writes to peripheral registers also works when executed by the ULP - but you might need to dig a bit into the macros/functions used (such as rtc_gpio_init and SET_PERI_REG_BITS), to find out what {READ,WRITE}_RTC_REG "instructions" they evaluate to.

The other pointer I can give, is that there exist a "bit-banged" implementation of I2C in ULP code. See: https://github.com/tomtor/ulp-i2c . Here the I2C protocol is essentially implemented in ULP code. The implementation uses assembler macros, which py-esp32-ulp does not support (yet?), so you would have to "manually expand" the macro calls to get it to run.

The ULP is quite a challenge to work with - a lot of trial and error involved. But there is a "compat test" in our test suite, which verifies that the I2C_RD opcode results in the same binary output as the "official" binutils-esp32-ulp assembler from Espressif would have output. So I would assume we're generating the right machine code.

Would be good to hear how you progress with this.

@sam0910
Copy link
Author

sam0910 commented Feb 14, 2022

Thank you so much! It is honor to have a good advice from both of owner and contributor.
There will be another hope that I could try out.
I will try tomtor/ulp-i2c, replace the macro to manual code line by line. It seems it doesn't use any I2C_RD/WR, and manually generate the clock signal for I2C. I will let you know :)

Great thanks to you, again.

@wnienhaus
Copy link
Collaborator

@sam0910 Did you ever get I2C to work from the ULP?

@sam0910
Copy link
Author

sam0910 commented Jun 4, 2023

It has been a year ago, time goes so fast.
sorry to tell you but I haven't tried your advise yet.
It is still on my Todo lists and need it, but it will be a tough work for me and a bit afraid to try.

by the way congrats! it is public micropython repo.

@wnienhaus
Copy link
Collaborator

There is now a disassembler in this project (see docs/disassembler.rst)!

Perhaps you can use that to disassemble the ulp binary, which https://github.com/tomtor/ulp-i2c (bit banged I2C) builds, to see how it's done there, or to get the assembly code as it was expanded by the macros.

@sam0910
Copy link
Author

sam0910 commented Jul 14, 2023

I've notified the disassembler by github notification, but I didn't know that is used for.
It is such a great updates for me, thank you so much. I'll definitely try it.

@sam0910 sam0910 closed this as completed Aug 29, 2023
@wnienhaus
Copy link
Collaborator

@sam0910 I see you closed this issues. Does that mean that you managed to get a bit-banged implementation (or something else) to work? Did the disassembler help you?

It would be great if you could share some hints as to what you got working and maybe how - I am sure others following this repo would also be interested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants