Questions about I2C... Mainly, how do I use it?


(Penguin) #1

So freedom metal sdk has support for uart and spi, but I don’t see I2C anywhere, including in the documentation. In the documentation, it just links to opencores.org. I’m a little confused about what this means. I’m assuming revb does include i2c support because it says so, but why is it supported differently than UART or SPI? And do I just use the opencore documentation to use it? I’m waiting on my account to be verified there so I’m posting here hoping someone has a guide or something because the revb doc has almost nothing on I2C.


#2

+1 for this, we’re trying to add I2C support to the Rust side of things as well and I got kinda stuck on this myself. There’s just the base address for the peripheral but no other info.


(Penguin) #3

Is there a git repo or something so I can follow the progress of the rust support you’re working on?


#4

Yup, the official rust-riscv repos are at: https://github.com/riscv-rust

Of main interest are the riscv, e310, 310x-hal, risc-rt and hifive1 repos. That said the rev B has been only added recently and is being worked on. You can find some of that WIP at https://github.com/Disasm/hifive1-revb-workspace

NOTE: I am not associated with the riscv rust group, just trying to help along as I go along. Right now we’re trying to figure out how to best handle memory/linking maps for the hifive1-revb.


#5

The answer to this is not obvious, because you need to know how “cores” work. Chip consists of different parts like CPU, memory, SPI0, SPI1, UART0, … Imagine that you are trying to build huge Lego city from multiple Lego sets. Some of the sets can be identical (UART0 and UART1 have the same registers) but located in different places on a floor ([UART]0 != [UART]1). Some of this peripherals are open-source and I2C is a good example. So you grab I2C from your local Lego shop and place on a floor. Now it’s I2C0. How to use it? Well, you could find everything from I2C documentation. In i2c_latest.tar.gz you can find i2c/trunk/doc/i2c_specs.pdf. Chapter 3 contains register definitions. Now you have a base address (from HiFive datasheet), register offsets (from i2c core datasheet) and a note “All I2C control register addresses are 4-byte aligned.” (from HiFive datasheet). So register 0 will be address+00, register 1 will be address+04 and so on.


(Penguin) #6

Thanks!


(Penguin) #7

This actually leaves me kinda where I started though, which is how do I get the documentation? I signed up to opencores, it said wait 2 days to be verified, then I never got an e-mail. Do I just try again with a different e-mail? It is kinda dumb and counter intuitive for documentation on an open source effort for i2c on a mcu to be locked behind 1) a registration wall and 2) an account verification wall. I’ve never had to do that with any arm mcus. You just google the datasheet and … you get all the relevant information.


#8

Oh, that’s strange. Sorry about that: I didn’t expect opencores to be so difficult to use.

Here is the file: i2c_specs.pdf.


(Paul Walmsley) #9

The actual HDL for the I2C block is here:

It’s a reimplementation, in Chisel, of the OpenCores I2C.


(Penguin) #10

Thanks @Disasm and @paulw ! Going to be working on this all day. Much appreciated.


#11

Current status: now I have i2c peripheral access bindings for Rust, but current driver implementation on top of them works in a strange way. I see communication with logic analyzer, but i2c peripheral sometimes leaves bus in invalid state.


#12

Now you can use i2c in Rust!

There is an example in riscv-rust-quickstart repo.

Driver code for those who interested: https://github.com/riscv-rust/e310x-hal/blob/6c1033009c304d1877f441f097e8bef703a29055/src/i2c.rs


(Penguin) #13

Awesome. Going to have to try this when I get back home. Thanks!