Library for Raspberry Pi

Version: 2014-03-06
Status: beta
SeeAlso:Raspberry Pi documentation, BCM2835 datasheet
Author: Advamation, Roland Koebler (support@advamation.de)
Copyright: (c) Advamation (info@advamation.de)
License:open-source / MIT
RCS:am_rpi.c,v 1.75 2014/05/02 11:49:25 rk Exp

Table of contents


1   init / exit / logging

1.1   init library + map registers

Check if it's a Raspberry Pi, initialize the library, increase the init-counter and map I/O memory. Does nothing (except increasing the init-counter), if already initialized.

am_rpi_init() and am_rpi_exit() should always be called pairwise.

Usage:AM_ERROR am_rpi_init(void)
Returns:0 on success, <0 on error

1.2   exit library + unmap registers

Decrease the init-counter. If 0, de-initialize the library, unmap I/O memory, close logfiles and reset log-level.

Usage:void am_rpi_exit(void)

1.3   configure logging

All messages up to "level" are printed and/or stored in the logfile. DEBUG/INFO are printed to stdout, MESSAGE/WARNING/CRITICAL/ERROR to stderr.

The available levels are:

  • AM_LOG_LEVEL_DEBUG
  • AM_LOG_LEVEL_INFO
  • AM_LOG_LEVEL_MESSAGE
  • AM_LOG_LEVEL_WARNING (default)
  • AM_LOG_LEVEL_CRITICAL
  • AM_LOG_LEVEL_ERROR
Usage:

AM_ERROR am_rpi_logging(enum am_log_level level, char const *logfile, enum am_log_level logfile_level)

Parameters:
  • level: log-level for "print"
  • logfile_level: log-level for the logfile
  • logfile: filename of the logfile (NULL: no logfile)
Returns:

0 on success, <0 on error (AM_ERROR_INVALID_ARGUMENT, AM_ERROR_IO if the logfile cannot be opened (see errno for details))

SeeAlso:

am_logging

2   system information

Note:These functions work even without initializing the library!

2.1   hardware information

Check if this is a Raspberry Pi and get its hardware information from /proc/cpuinfo.

Usage:

AM_ERROR am_rpi_info(char const **model, char const **rev, char const **manufacturer, uint16_t *rev_raw, uint64_t *serial)

Parameters:
  • model: output, Raspberry Pi model
  • rev: output, Raspberry Pi revision
  • manufacturer: output, Raspberry Pi manufacturer
  • rev_raw: output, Raspberry Pi raw revision number
  • serial: output, Raspberry Pi serial-number
Returns:

0 on success, AM_ERROR_DEVICE_NOT_SUPPORTED if this is no Raspberry Pi, AM_ERROR_MEMORY, AM_ERROR_IO, AM_ERROR_PERMISSIONS on error

Uses:

/proc/cpuinfo

Note:
  • The following values are currently known:

    model

    "A" "B" "UNKNOWN"

    rev

    "1.0" "1.0+ECN0001/Fuses mod, D14 removed" "2.0 256MB" "2.0 512MB" "UNKNOWN"

    manufacturer

    "Sony" "Egoman" "Quisda" "UNKNOWN"

  • No memory is allocated here for model/rev/manufacturer; the output pointers only point to static strings.

  • All output-parameters may be NULL if the value is not needed.

2.2   get Raspberry Pi revision-number

Get Raspberry Pi revision-number. This reads an internal variable (and is fast after am_rpi_init()), and uses am_rpi_info() otherwise.

Usage:AM_ERROR am_rpi_info_rev(uint16_t *rev_raw)
Returns:0 on success, <0 on error; after am_rpi_info, always 0 is returned

2.3   CPU-clock speed information

Usage:

AM_ERROR am_rpi_info_clk(uint16_t *clk, uint16_t *clk_min, uint16_t *clk_max)

Parameters:
  • clk: output, current clock in MHz
  • clk_min: output, min. clock in MHz
  • clk_max: output, max. clock in MHz
Returns:

0 on success, AM_ERROR_DEVICE_UNEXPECTED, AM_ERROR_MEMORY, AM_ERROR_PERMISSIONS, AM_ERROR_IO on error

Note:

All output-parameters may be NULL if the value is not needed.

Uses:

/sys/devices/system/cpu/cpu0/cpufreq/

2.4   memory size and usage information

Usage:

AM_ERROR am_rpi_info_memory(uint32_t *mem, uint32_t *used, uint32_t *free, uint32_t *free_buffers_cache)

Parameters:
  • mem: output, total memory in kB
  • used: output, used memory in kB without buffers/cache
  • free: output, free memory in kB
  • free_buffers_cache: output, free+buffer+cache memory in kB
Returns:

0 on success, AM_ERROR_DEVICE_UNEXPECTED, AM_ERROR_MEMORY, AM_ERROR_PERMISSIONS, AM_ERROR_IO on error

Note:
  • The returned total memory is usually less then the physical memory on the board, since the memory is shared between CPU and GPU.
  • All output-parameters may be NULL if the value is not needed.
Uses:

/proc/meminfo

2.5   temperature information

Usage:

AM_ERROR am_rpi_info_temperature(double *t)

Parameters:
  • t: output, CPU-temperature in °C
Returns:

0 on success, AM_ERROR_DEVICE_UNEXPECTED, AM_ERROR_MEMORY, AM_ERROR_PERMISSIONS, AM_ERROR_IO on error

Note:

All output-parameters may be NULL if the value is not needed.

Uses:

/sys/class/thermal/thermal_zone0/temp

3   miscellaneous functions

Note:These functions work even without initializing the library!

3.1   delay / wait / sleep

Depending on the length of a delay, there are several ways:

<= 1us:
Delay via busy-loop, more or less counting machine cycles. Depends on CPU clock and compiler optimization, and causes system load. See am_rpi_delay_nop*().
>= 1us:
Delay-loop, waiting for a timer to reach the desired delay. Compiler- and clock-independent, guarantees a minimum delay. Causes system load. See am_rpi_delay_us().
>= 60us:
Sleep-functions (e.g. nanosleep(), g_usleep()) are probably best. Although they may delay the program much longer than requested, they don't cause system load.

3.1.1   wait CPU-cycles

Wait a specified amount of CPU cycles. Note that the delay is not completely predictable and depends on the system load and the CPU frequency.

The measured values for 700 MHz, gcc -O3/-O4, idle, are roughly:

n ns
1 1.4
2 2.8
3 4.4
4 5.8
5 7.5
7 10.0
10 14.4
15 20.1
21 29.0
28 40.3
32 46.1
35 50.4
42 60.5
49 70.6
56 80.8
63 91.0
70 101.0
83 120.0
Usage:am_rpi_delay_nop1() am_rpi_delay_nop2() ... am_rpi_delay_nop256()

3.1.2   wait some µs

Wait (at least) a specified amount of microseconds in a busy-loop.

Usage:

void am_rpi_delay_us(uint16_t us)

Parameters:
  • us: microseconds to wait

4   system timer

Continuously running 64-bit, 1 MHz system timer.

4.1   read system timer

Usage:uint64_t am_rpi_timer(void)
Returns:64-bit timer value

4.2   read lower-half of system timer

Usage:uint32_t am_rpi_timer_lo(void)
Returns:32-bit timer value

5   I/O

Note:
  • Parameter gpios is a 32-bit-mask, containing 1 bit for every GPIO. Values from enum am_rpi_gpio should be used and can be combined, e.g.: GPIO_P1_7, GPIO_P1_7|GPIO_P1_10, GPIO_P1_26+GPIO_P1_7+GPIO_P1_22, GPIO_ALL.

5.1   I/O pins

GPIO connector:

Pin Description ALT0 ALT1 ALT2 ALT3 ALT4 ALT5 notes
P1-1 (+3.3V)             (max. 50mA draw)
P1-2 (+5V)              
P1-3 GPIO_0(Rev1) GPIO_2(Rev2) SDA0 SDA1 SA5 SA3 (res) (res) – – – – – – incl. 1k8 pull-up incl. 1k8 pull-up
P1-4 (+5V)              
P1-5 GPIO_1(Rev1) GPIO_3(Rev2) SCL0 SCL1 SA4 SA2 (res) (res) – – – – – – incl. 1k8 pull-up incl. 1k8 pull-up
P1-6 (GND)              
P1-7 GPIO_4 GPCLK0 SA1 (res) ARM_TDI  
P1-8 GPIO_14 UART0_TXD SD6 (res) UART1_TXD default: UART0_TXD
P1-9 (GND)              
P1-10 GPIO_15 UART0_RXD SD7 (res) UART1_RXD default: UART0_RXD
P1-11 GPIO_17 (res) SD9 (res) UART0_RTS SPI1_EN1_N UART1_RTS  
P1-12 GPIO_18 PCM_CLK SD10 (res) sl.SDA/MOSI SPI1_CE0_N PWM0  
P1-13 GPIO_21(Rev1) GPIO_27(Rev2) PCM_DOUT (res) SD13 (res) (res) (res) sl.CE_N SD1_DAT3 SPI1_SCLK ARM_TMS GPCLK1 (res)  
P1-14 (GND)              
P1-15 GPIO_22 (res) SD14 (res) SD1_CLK ARM_TRST  
P1-16 GPIO_23 (res) SD15 (res) SD1_CMD ARM_RTCK  
P1-17 (+3.3V)              
P1-18 GPIO_24 (res) SD16 (res) SD1_DAT0 ARM_TDO  
P1-19 GPIO_10 SPI0_MOSI SD2 (res)  
P1-20 (GND)              
P1-21 GPIO_9 SPI0_MISO SD1 (res)  
P1-22 GPIO_25 (res) SD17 (res) SD1_DAT1 ARM_TCK  
P1-23 GPIO_11 SPI0_SCLK SD3 (res)  
P1-24 GPIO_8 SPI0_CE0_N SD0 (res)  
P1-25 (GND)              
P1-26 GPIO_7 SPI0_CE1_N SW E_N/.. (res)  
P5-3 GPIO_28 SDA0 SA5 PCM_CLK (res)  
P5-4 GPIO_29 SCL0 SA4 PCM_FS (res)  
P5-5 GPIO_30 (res) SA3 PCM_DIN CTS0  
P5-6 GPIO_31 (res) SA2 PCM_DOUT RTS0  
CSI-14 GPIO_2(Rev1) GPIO_0(Rev2) SDA1 SDA0 SA3 SA5 (res) (res) – – – – – – incl. 1k?? pull-up, default: SDA incl. 1k?? pull-up, default: SDA
CSI-13 GPIO_3(Rev1) GPIO_1(Rev2) SCL1 SCL0 SA2 SA4 (res) (res) – – – – – – incl. 1k?? pull-up, default: SCL incl. 1k?? pull-up, default: SCL
CSI-12 GPIO_5 GPCLK1 SA0 (res) ARM_TDO default: CAM_CLK
CSI-11 GPIO_27(Rev1) GPIO_21(Rev2) (res) PCM_DOUT (res) SD13 (res) (res) SD1_DAT3 slave CE_N ARM_TMS SPI1_SCLK (res) GPCLK1 default: CAM_GPIO default: CAM_GPIO

GPIOs are not 5V-tolerant!

Note:
  • Better use GPIO_P1_# instead of GPIO_#.
  • 6 GPIOs were switched between Rev. 1.0 and Rev. 2.0 (GPIO_0/GPIO_2, GPIO_1/GPIO_3, GPIO_21/GPIO_27). This library transparently switches the GPIOs, so that all look like Rev. 2.0. But better always use GPIO_P1_# instead of GPIO_#.
  • 4 GPIOs were added on Rev. 2.0 (P5); they are ignored in Rev. 1.0.
  • GPIO_P1_8 + GPIO_P1_10 are used by the Linux serial console by default. To use them as GPIO, you have to disable the serial console and reboot.
  • For pull-up/pull-down-state on power-down, see am_rpi_gpio_pullupdown().

5.2   I/O configuration

5.2.1   configure I/O pins

Usage:

AM_ERROR am_rpi_gpio_config(uint32_t gpios, enum am_rpi_gpiomode mode)

Parameters:
  • gpios: GPIOs to configure
  • mode: GPIO_INPUT / GPIO_OUTPUT / GPIO_ALT0..5
Returns:

0 on success, AM_ERROR_INVALID_ARGUMENT on error

5.2.2   read I/O pin configuration

Usage:

int am_rpi_gpio_config_read(enum am_rpi_gpio gpio)

Parameters:
  • gpio: single GPIO
Returns:

enum am_rpi_gpiomode on success, AM_ERROR_INVALID_ARGUMENT on error

5.2.3   configure GPIO-pin pull-up/pull-down

Usage:

AM_ERROR am_rpi_gpio_pullupdown(uint32_t gpios, enum am_rpi_pullupdown pullupdown)

Parameters:
  • gpios: GPIOs to configure
  • pullupdown: DISABLE / PULL_DOWN / PULL_UP
Returns:

0 on success, AM_ERROR_INVALID_ARGUMENT on error

Note:

On power-down, the following pull-ups/-downs are active:

  • pull-up: GPIO 0-8 / P1_3/5/7/24/26, CSI_12/13/14
  • pull-down: GPIO 9-27, 30-31 / P1_8/10/11/12/13/15/16/18/19/21/22/23, P5_5/6, CSI_11
  • none: GPIO 28, 29 / P5_3/4

5.3   GPIO

5.3.1   read GPIO(s)

Usage:

uint32_t am_rpi_gpio_read(uint32_t gpios)

Parameters:
  • gpios: GPIOs to read, 0xffffffff for all
Returns:

read input levels, masked by gpios

5.3.2   write GPIO output level

Usage:

AM_ERROR am_rpi_gpio_write(uint32_t gpios, bool level)

Parameters:
  • gpios: GPIOs to write
  • level: 0/FALSE to clear, 1/TRUE to set
Returns:

0 on success, AM_ERROR_INVALID_ARGUMENT on error

5.3.3   set GPIO(s)

Usage:

AM_ERROR am_rpi_gpio_set(uint32_t gpios)

Parameters:
  • gpios: GPIOs to set
Returns:

0 on success, AM_ERROR_INVALID_ARGUMENT on error

5.3.4   clear GPIO(s)

Usage:

AM_ERROR am_rpi_gpio_clr(uint32_t gpios)

Parameters:
  • gpios: GPIOs to clear
Returns:

0 on success, AM_ERROR_INVALID_ARGUMENT on error

5.4   SPI

Broadcom BCM2835 contains 3 SPI interfaces: 1 full-featured SPI (SPI0) and two mini-SPIs (SPI1, SPI2). But only SPI0 is accessible on the Raspberry Pi.

This library supports concurrent access to the SPI from different programs, which use this library, by using automatic locks:

  • Before every communication, the SPI is locked. If another program has currently locked the SPI, the functions wait until the SPI becomes unlocked or a timeout occurs.
  • After successfully locking the SPI, the SPI is reconfigured.
  • After communication, the SPI is unlocked again.
  • It's also possible to manually lock the SPI, but this should be used with care, since it could prevent other programs from accessing SPI at all.

If you want to use SPI from different threads in a program, use e.g. a mutex to make sure only 1 thread accesses the SPI at the same time. If the threads use different SPI-configurations, make sure to reconfigure the SPI after acquiring the mutex.

Note:
  • SPI is msb-first
  • TX- and RX-FIFO are 64 bytes.

5.4.1   configure SPI-pins

Use GPIO_P1_21 as MISO, GPIO_P1_19 as MOSI, GPIO_P1_23 as SCK, and optionally GPIO_P1_24 as CS0 / GPIO_P1_26 as CS1

Usage:

void am_rpi_spi_pins(bool cs0, bool cs1)

Parameters:
  • CS0: use GPIO_P1_24 as CS0 / SPI0_CE0_N?
  • CS1: use GPIO_P1_26 as CS1 / SPI0_CE1_N?

5.4.2   manually lock SPI

Wait until the SPI is unlocked and manually lock (and configure) the SPI.

Usually, it's not necessary to use this function, since am_rpi_spi_start()/_stop()/_comm()/_comm_writeN()/_write_window() automatically lock and unlock the SPI. But the SPI may be locked manually, e.g. if several SPI-communications must directly follow each other, or to prevent other programs to access the SPI.

Note that you additionally have to use a mutex, if you're accessing the SPI from several threads in the same program.

Always use am_rpi_spi_unlock() for every successful call to this function.

Usage:

AM_ERROR am_rpi_spi_lock(int32_t timeout_ms)

Parameters:
  • timeout_ms: timeout in ms (0..65535), 0=non-blocking, -1=use auto-locking timeout
Returns:

0 on success, AM_ERROR_BUSY after timeout

5.4.3   manually unlock SPI

Manually unlock the SPI.

This is usually only necessary after am_rpi_spi_lock(); otherwise, locking and unlocking is automatically done by am_rpi_spi_start()/_stop().

Usage:void am_rpi_spi_unlock(void)

5.4.4   set SPI-auto-locking timeout

Set timeout, after which SPI-communication-functions return AM_ERROR_BUSY if they cannot lock the SPI.

Usage:void am_rpi_spi_locking_timeout(uint16_t timeout_ms)
Parameters:timeout_ms: timeout in ms (default: 1000ms)

5.4.5   configure SPI

Usage:

AM_ERROR am_rpi_spi_config(enum am_rpi_spi_mode mode, enum am_rpi_spi_clkcfg clkcfg, enum am_rpi_spi_cspol cspol0, enum am_rpi_spi_cspol cspol1)

Parameters:
  • mode: SPI mode
  • clkcfg: SPI clock polarity and clock phase
  • cspol0/1: SPI chip-select polarity
Returns:

0 on success, AM_ERROR_INVALID_ARGUMENT/AM_ERROR_NOT_IMPLEMENTED on error

Note:
  • If a parameter is -1, the appr. configuration is not changed.
  • If the SPI is currently not locked by this program, configuring the SPI is delayed until the next lock.

5.4.6   read SPI-configuration

Usage:

void am_rpi_spi_config_read(enum am_rpi_spi_mode *mode, enum am_rpi_spi_clkcfg *clkcfg, enum am_rpi_spi_cspol *cspol0, enum am_rpi_spi_cspol *cspol1)

Parameters:
  • mode: output, SPI mode
  • clkcfg: output, SPI clock polarity and clock phase
  • cspol0/1: output, SPI chip-select polarity
Note:
  • This returns the current configuration, which may differ from the values set by am_rpi_spi_config() if the SPI is not locked.
  • All output-parameters may be NULL if the value is not needed.

5.4.7   set SPI clock

Usage:

AM_ERROR am_rpi_spi_clk(enum am_rpi_spi_clk clkdiv)

Parameters:
  • clkdiv: clock divisor (SPI_CLK_* or 4/6/8/10/../65536)
Returns:

0 on success, AM_ERROR_INVALID_ARGUMENT on error

Note:
  • SPI-speed is 250 MHz / clkdiv
  • If the SPI is currently not locked by this program, setting the SPI-clock is delayed until the next lock.

5.4.8   read SPI clock

Usage:

void am_rpi_spi_clk_read(enum am_rpi_spi_clk *clkdiv)

Parameters:
  • clkdiv: output, clock divisor
Note:
  • This returns the current clock, which may differ from the value set by am_rpi_spi_clk() if the SPI is not locked.
  • All output-parameters may be NULL if the value is not needed.

5.4.9   start/init SPI

Auto-lock SPI, clear FIFOs and enable SPI. Also reconfigure SPI if it was configured by another program.

Must be called before writing any data to SPI FIFOs.

Usage:

AM_ERROR am_rpi_spi_start(int cs)

Parameters:
  • cs: chip-select to use (0 for CS0, 1 for CS1 or -1 for none)
Returns:

0 on success, AM_ERROR_INVALID_ARGUMENT/AM_ERROR_BUSY on error

5.4.10   stop/end SPI

Stop and auto-unlock SPI, and clear the SPI-buffers. Must be called after every SPI communication.

Usage:void am_rpi_spi_stop(void)

5.4.11   write byte to SPI FIFO

Usage:

AM_ERROR am_rpi_spi_write_byte(char byte)

Parameters:
  • byte: byte to send
Returns:

0 on success, AM_ERROR_BUFFER_FULL if the TX FIFO is full

5.4.12   read byte from SPI FIFO

Usage:

AM_ERROR am_rpi_spi_read_byte(char *byte)

Parameters:
  • byte: output, received byte, may be NULL if not needed
Returns:

0 on success, AM_ERROR_BUFFER_EMPTY if the RX FIFO is empty

Note:

SPI is symmetric, so for each written byte, one byte must be read. Otherwise the receive-buffer will run full and stop the SPI. Alternatively, the SPI-RX-buffer may be cleared.

5.4.13   write byte to SPI FIFO (blocking) + return received byte (if any)

This is useful to send bytes very quickly.

Usage:

int am_rpi_spi_rw(char byte)

Parameters:
  • byte: byte to send
Returns:

received byte, or AM_ERROR_BUFFER_EMPTY if the RX FIFO was empty

5.4.14   wait until SPI is done

Also clear the SPI-RX-buffer.

Usage:void am_rpi_spi_wait_done(void)

5.4.15   communicate over SPI

  • auto-lock + start/init SPI
  • write + read data
  • wait until done
  • stop + auto-unlock SPI
Usage:

AM_ERROR am_rpi_spi_comm(int cs, unsigned int len, char const *txdata, char *rxdata)

Parameters:
  • cs: chip-select to use (0/1 or -1 for none)
  • len: number of bytes to send/receive
  • txdata: transmit-data
  • rxdata: receive-memory, may be NULL
Returns:

0 on success, AM_ERROR_INVALID_ARGUMENT/AM_ERROR_BUSY on error

5.4.16   communicate over SPI: write some data N times

  • auto-lock + start/init SPI
  • write some data (prefix)
  • write data several times
  • write some more data (suffix)
  • wait until done
  • stop + auto-unlock SPI
Usage:

AM_ERROR am_rpi_spi_comm_writeN(int cs, unsigned int pre_len, char const* pre_data, unsigned int repeat, unsigned int len, char const *txdata, unsigned int suf_len, char const *suf_data)

Parameters:
  • cs: chip-select to use (0/1 or -1 for none)
  • pre_len: length of prefix
  • pre_data: prefix-data
  • repeat: number of repeats
  • len: length of data
  • txdata: data
  • suf_len: length of suffix
  • suf_data: suffix-data
Returns:

0 on success, AM_ERROR_INVALID_ARGUMENT/AM_ERROR_BUSY on error

5.4.17   communicate over SPI: write a data-window

  • auto-lock and start/init SPI
  • write data from a window
  • wait until done
  • stop and auto-unlock SPI
Usage:

AM_ERROR am_rpi_spi_write_window(int cs, uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t rowstride, char const *txdata, bool swap)

Parameters:
  • cs: chip-select to use (0/1 or -1 for none)
  • x0/y0: start of the data-window
  • w: width of the data-window
  • h: height of the data-window
  • rowstride: length of a data-row
  • txdata: transmit-data
  • swap: 0=no swap, 1=swap bytes 2-byte-wise
Returns:

0 on success, AM_ERROR_INVALID_ARGUMENT/AM_ERROR_BUSY on error

Note:

If swap=1, w must be even!

5.4.18   SPI interface

SPI interface abstraction.

If a driver for an SPI-device should not be Raspberry Pi-dependent, better use this abstraction-layer instead of the functions above.

Usage:
AM_ERROR ret;
AM_SPI_INTERFACE *my_spi;
my_spi = am_rpi_spi;
char txdata[...], rxdata[...];

...

ret = my_spi->comm(cs, len, txdata, rxdata);
SeeAlso:

documentation of am_rpi_spi_comm(), advamation.h

5.5   I2C

Broadcom BCM2835 contains 3 "BSC"s (Broadcom Serial Controller), which are compatible to fast-mode (400 Kb/s) I2C v2.1:

  • BSC0: on P1 on Rev. 1.0, on P5/CSI on Rev. 2.0
  • BSC1: on P1 on Rev. 2.0, on SCI on Rev. 1.0
  • BSC2: dedicated to HDMI and should not be used otherwise.

Currently, only the BSC on P1 is supported.

The BSC supports single-master-mode, and 7-/10-bit addressing, and has 16-byte-FIFOs.

This library supports concurrent access to the I2C from different programs, which use this library:

  • Before every communication, the I2C is locked. If another program has currently locked the I2C, the functions wait until the I2C becomes unlocked or a timeout occurs.
  • After successfully locking the I2C, the I2C is reconfigured.
  • After communication, the I2C is unlocked again.
  • It's also possible to manually lock the I2C, but this should be used with care, since it could prevent other programs from accessing I2C at all.

If you want to use I2C from different threads in a program, use e.g. a mutex to make sure only 1 thread accesses the I2C at the same time. If the threads use different I2C-speeds, make sure to reconfigure the I2C-clock after acquiring the mutex.

5.5.1   configure I2C-pins

Use GPIO_P1_3 as SDA, GPIO_P1_5 as SCL.

Usage:void am_rpi_i2c_pins(void)

5.5.2   en-/disable I2C

I2C has to be enabled before any data can be written/read. But the I2C-registers can also be accessed when I2C is disabled.

Note that you should only disable the I2C if you are sure that no other application uses the I2C; otherwise, you will break other programs!

Usage:

void am_rpi_i2c_enable(bool enable)

Parameters:
  • enable: 0=disable I2C, 1=enable I2C

5.5.3   check if I2C is enabled

Usage:bool am_rpi_i2c_enabled(void)
Returns:0 if disabled, 1 if enabled

5.5.4   manually lock I2C

Wait until the I2C is unlocked and manually lock (and configure) the I2C.

Usually, it's not necessary to use this function, since am_rpi_i2c_read()/_write()/_write_read() (and its 10-bit-address variants) automatically lock and unlock the I2C. But the I2C may be locked manually, e.g. if several I2C-communications must directly follow each other, or to prevent other programs to access the I2C.

Note that you additionally have to use a mutex, if you're accessing the I2C from several threads in the same program.

Always use am_rpi_i2c_unlock() for every successful call to this function.

Usage:

AM_ERROR am_rpi_i2c_lock(int32_t timeout_ms)

Parameters:
  • timeout_ms: timeout in ms (0..65535), 0=non-blocking, -1=use auto-locking timeout
Returns:

0 on success, AM_ERROR_BUSY after timeout

5.5.5   manually unlock I2C

Manually unlock the I2C.

This is usually only necessary after am_rpi_i2c_lock(); otherwise, locking and unlocking is automatically done by am_rpi_i2c_read()/_write()/write_read().

Usage:void am_rpi_i2c_unlock(void)

5.5.6   set I2C-auto-locking timeout

Set timeout, after which I2C-communication-functions return AM_ERROR_BUSY if they cannot lock the I2C.

Usage:void am_rpi_i2c_locking_timeout(uint16_t timeout_ms)
Parameters:timeout_ms: timeout in ms (default: 1000ms)

5.5.7   set I2C clock

Usage:

AM_ERROR am_rpi_i2c_clk(enum am_rpi_i2c_clk clkdiv)

Parameters:
  • clkdiv: clock divisor (I2C_CLK_...kHz or 4/6/8/10/.../65536)
Returns:

0 on success, AM_ERROR_INVALID_ARGUMENT on error

Note:
  • The I2C core clock is 250 MHz; default-clkdiv is 1500 (166.7kHz). (The Raspberry Pi datasheet is wrong, here.)
  • If the I2C is currently not locked by this program, setting the I2C-clock is delayed until the next lock.

5.5.8   read I2C clock

Usage:

void am_rpi_i2c_clk_read(enum am_rpi_i2c_clk *clkdiv)

Parameters:
  • clkdiv: output, clock divisor
Note:
  • This returns the current configuration, which may differ from the values set by am_rpi_i2c_clk() if the I2C is not locked.
  • All output-parameters may be NULL if the value is not needed.

5.5.9   read byte from I2C-FIFO

(low-level function without locking)

Usage:

AM_ERROR am_rpi_i2c_read_byte(char *byte)

Parameters:
  • byte: receive-memory, may be NULL
Returns:

0 on success, AM_ERROR_BUFFER_EMPTY if RX FIFO is empty, AM_ERROR_COMM_FAILED on timeout/ACK error

5.5.10   write byte to I2C-FIFO

(low-level function without locking)

Usage:

AM_ERROR am_rpi_i2c_write_byte(char byte)

Parameters:
  • byte: byte to send
Returns:

0 on success, AM_ERROR_BUFFER_FULL if TX FIFO is full, AM_ERROR_COMM_FAILED on timeout/ACK error

5.5.11   wait until I2C is done

(low-level function without locking)

Usage:AM_ERROR am_rpi_i2c_wait_done(void)
Returns:0 on success, AM_ERROR_COMM_FAILED on timeout/ACK error

5.5.12   read data from I2C

  • auto-lock I2C and set I2C-speed
  • reset errors/done, set address + length, clear FIFO
  • start transfer
  • read data
  • wait until done
  • auto-unlock I2C
Usage:

AM_ERROR am_rpi_i2c_read(uint8_t address, uint16_t rxlen, char *rxdata)

Parameters:
  • address: 7-bit I2C-slave address
  • rxlen: number of bytes to read
  • rxdata: receive-memory, may be NULL
Returns:

0 on success, AM_ERROR_INVALID_ARGUMENT on invalid address, AM_ERROR_COMM_FAILED on timeout/ACK error, AM_ERROR_BUSY on locking-timeout

5.5.13   write data to I2C

  • auto-lock I2C and set I2C-speed
  • reset errors/done, set address + length + FIFO
  • start transfer
  • write more data to FIFO
  • wait until done
  • auto-unlock I2C
Usage:

AM_ERROR am_rpi_i2c_write(uint8_t address, uint16_t txlen, char const *txdata)

Parameters:
  • address: 7-bit I2C-slave address
  • txlen: number of bytes to send
  • txdata: transmit-data
Returns:

0 on success, AM_ERROR_INVALID_ARGUMENT on invalid address, AM_ERROR_COMM_FAILED on timeout/ACK error, AM_ERROR_BUSY on locking-timeout

5.5.14   write data to I2C, then read data

  • auto-lock I2C and set I2C-speed
  • reset errors/done, set address + tx-length + FIFO
  • start transfer
  • write more data to FIFO
  • wait until TX-FIFO is empty
  • set rx-length
  • repeated start + reset done
  • read data
  • wait until done
  • auto-unlock I2C
Usage:

AM_ERROR am_rpi_i2c_write_read(uint8_t address, uint16_t txlen, char const *txdata, uint16_t rxlen, char *rxdata)

Parameters:
  • address: 7-bit I2C-slave address
  • txlen: number of bytes to send
  • txdata: transmit-data
  • rxlen: number of bytes to read
  • rxdata: receive-memory, may be NULL
Returns:

0 on success, AM_ERROR_INVALID_ARGUMENT on invalid address, AM_ERROR_COMM_FAILED on timeout/ACK error, AM_ERROR_BUSY on locking-timeout

5.5.15   read data from I2C with 10-bit slave-address

Like am_rpi_i2c_read(), but with 10-bit slave-address.

Usage:

AM_ERROR am_rpi_i2c_read10(uint16_t address, uint16_t rxlen, char *rxdata)

Parameters:
  • address: 10-bit I2C-slave address
  • rxlen: number of bytes to read
  • rxdata: receive-memory, may be NULL
Returns:

0 on success, AM_ERROR_INVALID_ARGUMENT on invalid address, AM_ERROR_COMM_FAILED on timeout/ACK error, AM_ERROR_BUSY on locking-timeout

5.5.16   write data to I2C with 10-bit slave-address

Like am_rpi_i2c_write(), but with 10-bit slave-address.

Usage:

AM_ERROR am_rpi_i2c_write10(uint16_t address, uint16_t txlen, char const *txdata)

Parameters:
  • address: 10-bit I2C-slave address
  • txlen: number of bytes to send (max. 65534)
  • txdata: transmit-data
Returns:

0 on success, AM_ERROR_INVALID_ARGUMENT on invalid address/len, AM_ERROR_COMM_FAILED on timeout/ACK error, AM_ERROR_BUSY on locking-timeout

5.5.17   write data to I2C, then read data, 10-bit slave-address

Like am_rpi_i2c_write_read(), but with 10-bit slave-address.

Usage:

AM_ERROR am_rpi_i2c_write_read10(uint16_t address, uint16_t txlen, char const *txdata, uint16_t rxlen, char *rxdata)

Parameters:
  • address: 10-bit I2C-slave address
  • txlen: number of bytes to send (max. 65534)
  • txdata: transmit-data
  • rxlen: number of bytes to read
  • rxdata: receive-memory, may be NULL
Returns:

0 on success, AM_ERROR_INVALID_ARGUMENT on invalid address, AM_ERROR_COMM_FAILED on timeout/ACK error, AM_ERROR_BUSY on locking-timeout

5.5.18   I2C interface

I2C interface abstraction.

If a driver for an I2C-device should not be Raspberry Pi-dependent, better use this abstraction-layer instead of the functions above.

Usage:
AM_ERROR ret;
AM_I2C_INTERFACE *my_i2c;
my_i2c = am_rpi_i2c;

ret = my_i2c->read(...);
ret = my_i2c->write(...);
ret = my_i2c->write_read(...);
ret = my_i2c->read10(...);
ret = my_i2c->write10(...);
ret = my_i2c->write_read10(...);
SeeAlso:

documentation of the above functions, advamation.h

5.5.19   I2C-communication with Advamation RS-485-/I2C-protocol

Communicate with a I2C-device with the Advamation RS-485-/I2C-protocol, incl. CRC/PEC.

Usage:

AM_ERROR am_rpi_i2c_prot(uint8_t address, enum am_cmd cmd, unsigned int txlen, char const *txdata, unsigned int rxlen, unsigned int *received_len, char *rxdata)

Parameters:
  • address: 7-bit I2C-slave address
  • cmd: I2C-protocol-command
  • txlen: number of data-bytes to send
  • txdata: transmit-data-bytes (0..16)
  • rxlen: max. number of data-bytes to read (0..16)
  • received_len: output, number of really received bytes (may be NULL)
  • rxdata: receive-memory (may be NULL)
Returns:

0 on success, <0 on error (AM_ERROR_INVALID_ARGUMENT on invalid address/txlen/rxlen, AM_ERROR_COMM_FAILED on timeout/ACK error, AM_ERROR_COMM_CRC on incorrect CRC, AM_ERROR_COMM_TOOSHORT if less then rxlen bytes received), AM_ERROR_BUSY on locking-timeout

SeeAlso:

advamation.h, am_rpi_i2c_write_read()

6   UI-functions

6.1   map enum GPIO_* to a string

Usage:const char* am_rpi_gpio2str(enum am_rpi_gpio gpio)
Returns:string or "unknown"

6.2   map string to enum GPIO_*

Usage:enum am_rpi_gpio am_rpi_str2gpio(char const *s)
Returns:found enum or -1