Browse Source

Add i2c eeprom example.

master
flabbergast 1 year ago
parent
commit
124fe29898
9 changed files with 368 additions and 1 deletions
  1. 1
    0
      .gitignore
  2. 4
    0
      README.md
  3. 38
    0
      i2c_eep/Makefile.f0
  4. 38
    0
      i2c_eep/Makefile.l0
  5. 29
    0
      i2c_eep/Makefile.l0btld
  6. 201
    0
      i2c_eep/i2c_eep.c
  7. 39
    0
      i2c_eep/serial_helper.c
  8. 17
    0
      i2c_eep/serial_helper.h
  9. 1
    1
      libopencm3.rules.mk

+ 1
- 0
.gitignore View File

@@ -4,3 +4,4 @@
*.hex
*.bin
*.map
.gdb_config_bmp

+ 4
- 0
README.md View File

@@ -22,6 +22,10 @@ The board presents itself as a serial port (CDC). It echoes back what it receive

L052 only. This is the DFU bootloader that I use on the bat boards with L052. More info about it on [the bat board] main page.

### i2c_eep

Writes a few bytes, then reads a few bytes, from a standard I2C EEPROM. The bytes read are printed over USART (on PA9/PA10). Connections and address can be seen in the code (different setups for F0 and L0).

## General setup notes

You are expected to a C compiler (for ARM) and some development tools (e.g. make and git) installed and ready to use. You can get a [toolchain from arm.com]; or use one provided by your system package manager (if you're on a normal system like some linux, bsd or mac). For the development tools, use your package manager.

+ 38
- 0
i2c_eep/Makefile.f0 View File

@@ -0,0 +1,38 @@
##
## This file is part of the libopencm3 project.
##
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
##
## This library is free software: you can redistribute it and/or modify
## it under the terms of the GNU Lesser General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This library is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public License
## along with this library. If not, see <http://www.gnu.org/licenses/>.
##

BINARY = i2c_eep

OBJS += serial_helper.o

OPENCM3_DIR=../libopencm3
LDSCRIPT = $(OPENCM3_DIR)/lib/stm32/f0/stm32f07xzb.ld

include ../common.f0.mk

BMP_PORT = /dev/cu.usbmodemE0BABAF1

.gdb_config_bmp:
echo > .gdb_config_bmp "file $(BINARY).elf\ntarget extended-remote $(BMP_PORT)\nmonitor version\nmonitor swdp_scan\nattach 1\nload\nbreak main\nc\n"

debug_bmp: .gdb_config_bmp $(BINARY).elf
cgdb -d $(GDB) -- \
--command=.gdb_config_bmp \
$(BINARY).elf


+ 38
- 0
i2c_eep/Makefile.l0 View File

@@ -0,0 +1,38 @@
##
## This file is part of the libopencm3 project.
##
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
##
## This library is free software: you can redistribute it and/or modify
## it under the terms of the GNU Lesser General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This library is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public License
## along with this library. If not, see <http://www.gnu.org/licenses/>.
##

BINARY = i2c_eep

OBJS += serial_helper.o

OPENCM3_DIR=../libopencm3
LDSCRIPT = $(OPENCM3_DIR)/lib/stm32/l0/stm32l0xx8.ld

include ../common.l0.mk

BMP_PORT = /dev/cu.usbmodemE0BABAF1

.gdb_config_bmp:
echo > .gdb_config_bmp "file $(BINARY).elf\ntarget extended-remote $(BMP_PORT)\nmonitor version\nmonitor swdp_scan\nattach 1\nload\nbreak main\nc\n"

debug_bmp: .gdb_config_bmp $(BINARY).elf
cgdb -d $(GDB) -- \
--command=.gdb_config_bmp \
$(BINARY).elf


+ 29
- 0
i2c_eep/Makefile.l0btld View File

@@ -0,0 +1,29 @@
##
## This file is part of the libopencm3 project.
##
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
##
## This library is free software: you can redistribute it and/or modify
## it under the terms of the GNU Lesser General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This library is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public License
## along with this library. If not, see <http://www.gnu.org/licenses/>.
##

BINARY = i2c_eep

OBJS += serial_helper.o

OPENCM3_DIR=../libopencm3
LDSCRIPT = ../l052-bldr.ld
DEFS += -DBOOTLOADER8K

include ../common.l0.mk


+ 201
- 0
i2c_eep/i2c_eep.c View File

@@ -0,0 +1,201 @@
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/flash.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/i2c.h>

#include <libopencm3/stm32/usart.h>
#include "serial_helper.h"


static void usart_setup(void)
{
/* Enable clocks for GPIO port A (for GPIO_USART1_TX) and USART1. */
rcc_periph_clock_enable(RCC_GPIOA);
rcc_periph_clock_enable(RCC_USART1);

#if defined(STM32F0)
/* USART1 pins: PA9/TX PA10/RX */
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9|GPIO10);
gpio_set_af(GPIOA, GPIO_AF1, GPIO9|GPIO10);
#elif defined(STM32L0)
/* USART1 pins: PA9/TX PA10/RX */
gpio_set_af(GPIOA, GPIO_AF4, GPIO9|GPIO10);
gpio_set_output_options(GPIOA, GPIO_OTYPE_OD, GPIO_OSPEED_HIGH, GPIO9|GPIO10);
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9|GPIO10);
#endif

/* Setup UART parameters. */
usart_set_baudrate(USART1, 115200);
usart_set_databits(USART1, 8);
usart_set_parity(USART1, USART_PARITY_NONE);
usart_set_stopbits(USART1, USART_STOPBITS_1);
//usart_set_stopbits(USART1, USART_CR2_STOP_1_0BIT);
usart_set_mode(USART1, USART_MODE_TX_RX);
usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE);

/* Finally enable the USART. */
usart_enable(USART1);
}

static void gpio_setup(void)
{
rcc_periph_clock_enable(RCC_GPIOA);

/* Set PA15 for LED */
gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO15);
}

static void i2c_setup(void)
{
uint32_t i2c;
#if defined(STM32F0)
/* Enable clocks for I2C2. */
rcc_periph_clock_enable(RCC_I2C2);
rcc_periph_clock_enable(RCC_GPIOB);

/* Set alternate functions for the SCL and SDA pins of I2C2. */
gpio_set_af(GPIOB, GPIO_AF1, GPIO10|GPIO11);
gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO10|GPIO11);

i2c = I2C2;

#elif defined(STM32L0)
/* Enable clocks for I2C1. */
rcc_periph_clock_enable(RCC_I2C1);
rcc_periph_clock_enable(RCC_GPIOB);

/* Set alternate functions for the SCL and SDA pins of I2C2. */
gpio_set_af(GPIOB, GPIO_AF4, GPIO8|GPIO9);
gpio_set_output_options(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_HIGH, GPIO8|GPIO9);
gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO8|GPIO9);

i2c = I2C1;
#endif /* STM32L0 */
i2c_reset(i2c);

/* Disable the I2C before changing any configuration. */
i2c_peripheral_disable(i2c);

/* setup from libopencm3-examples */
i2c_enable_analog_filter(i2c);
i2c_set_digital_filter(i2c, I2C_CR1_DNF_DISABLED);
i2c_set_speed(i2c, i2c_speed_sm_100k, 8);
i2c_enable_stretching(i2c);
i2c_set_7bit_addr_mode(i2c);

/* If everything is configured -> enable the peripheral. */
i2c_peripheral_enable(i2c);
}


#if defined(STM32L0)
static void clock_setup_l0(void)
{
/* After a reset, the system uses MSI@2.1MHz. */
/* end result: 32MHz PLLVCO from HSI16,
* no system/periph clock divide.
*/

/* increase the latency to 1 wait state (we'll be speeding up) */
flash_set_ws(1);

/* turn on HSI16 */
rcc_osc_on(RCC_HSI16);
rcc_wait_for_osc_ready(RCC_HSI16);

/* run AHB, APB1, APB2 at full speed */
rcc_set_hpre(RCC_CFGR_HPRE_NODIV);
rcc_set_ppre1(RCC_CFGR_PPRE1_NODIV);
rcc_set_ppre2(RCC_CFGR_PPRE2_NODIV);

/* turn off PLL and wait for it to fully stop */
rcc_osc_off(RCC_PLL);
while (RCC_CR & RCC_CR_PLLRDY);

/* set PLL source to HSI16 */
RCC_CFGR &= ~(1<<16); // RCC_CFGR_PLLSRC

/* set up PLL */
rcc_set_pll_multiplier(RCC_CFGR_PLLMUL_MUL4);
rcc_set_pll_divider(RCC_CFGR_PLLDIV_DIV2);

/* turn on and switch to PLL */
rcc_osc_on(RCC_PLL);
rcc_wait_for_osc_ready(RCC_PLL);
rcc_set_sysclk_source(RCC_PLL);

rcc_ahb_frequency = 32000000;
rcc_apb1_frequency = 32000000;
rcc_apb2_frequency = 32000000;
}
#endif /* STM32L0 */

int main(void)
{
#if defined(BOOTLOADER8K)
# define SCB_VTOR MMIO32(0xE000ED08)
SCB_VTOR = (uint32_t) 0x08002000;
#endif /* BOOTLOADER8K */

#if defined(STM32F0)
uint32_t i2c = I2C2;
#elif defined(STM32L0)
uint32_t i2c = I2C1;
#endif /* STM32L0 */
uint8_t eeprom_addr = 0x50;

#if defined(STM32F0)
rcc_clock_setup_in_hsi_out_48mhz();
#elif defined(STM32L0)
clock_setup_l0();
#endif
gpio_setup();
usart_setup();
i2c_setup();

/* Send a message on USART1. */
pstr("stm\r\n");

uint8_t temp[10];
uint8_t wb[2];

// one byte addresses for smaller epproms
temp[0] = 0;
// bytes to write
temp[1] = 0x11;
temp[2] = 0x22;
temp[3] = 0x33;

// write
i2c_transfer7(i2c, eeprom_addr, temp, 4, NULL, 0);

uint32_t t;
// the pause needs to be long enough for the eeprom to finish
// writing the data above; otherwise the 'read' call below
// hangs
t = 500000;
while(t-- > 0)
__asm__("nop");

// two byte addresses for bigger eeproms (change also transfer7 call!)
//wb[0] = (uint8_t)( 0 >>8);
//wb[1] = (uint8_t)( 0 &0xFF);
// one byte addresses for smaller epproms (change also transfer7 call!)
wb[0] = 0;

// read
i2c_transfer7(i2c, eeprom_addr, wb, 1, temp, 10);

gpio_set(GPIOA, GPIO15); /* LED on */

uint8_t i;
for(i=0; i<10; i++)
phex(temp[i]);
pent();

while (1); /* Halt. */

return 0;
}

// vim: tabstop=4:shiftwidth=4:noexpandtab

+ 39
- 0
i2c_eep/serial_helper.c View File

@@ -0,0 +1,39 @@
#include "serial_helper.h"

void phex4(uint8_t c) {
usart_send_blocking(P_USART, (uint8_t)(c + ((c < 10) ? '0' : 'A' - 10)));
}

void phex(uint8_t c) {
phex4((c>>4));
phex4((c&15));
}

void phex16(uint16_t c) {
phex((uint8_t)(c>>8));
phex((uint8_t)c);
}

void phex24(uint32_t c) {
phex16((uint16_t)((c>>8)&0xFFFF));
phex((uint8_t)c);
}

void phex32(uint32_t c) {
phex16((uint16_t)(c>>16));
phex16((uint16_t)(c&0xFFFF));
}

void pent(void) {
usart_send_blocking(P_USART, '\r');
usart_send_blocking(P_USART, '\n');
}

void pstr(char *s) {
uint16_t i = 0;
while(s[i]) {
usart_send_blocking(P_USART, (uint8_t)(s[i++]));
}
}

// vim: tabstop=4:shiftwidth=4:noexpandtab

+ 17
- 0
i2c_eep/serial_helper.h View File

@@ -0,0 +1,17 @@
#ifndef SERIAL_HELPER_H
#define SERIAL_HELPER_H

#include <libopencm3/stm32/usart.h>

#define P_USART USART1

void phex4(uint8_t c);
void phex(uint8_t c);
void phex16(uint16_t c);
void phex24(uint32_t c);
void phex32(uint32_t c);
void pent(void);

void pstr(char *s);

#endif /* SERIAL_HELPER_H */

+ 1
- 1
libopencm3.rules.mk View File

@@ -72,7 +72,7 @@ STFLASH = $(shell which st-flash)
STYLECHECK := /checkpatch.pl
STYLECHECKFLAGS := --no-tree -f --terse --mailback
STYLECHECKFILES := $(shell find . -name '*.[ch]')
OPT := -Os
OPT ?= -Os
CSTD ?= -std=c99



Loading…
Cancel
Save