Add i2c eeprom example.
This commit is contained in:
parent
ef9fd2db6a
commit
124fe29898
9 changed files with 368 additions and 1 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,3 +4,4 @@
|
|||
*.hex
|
||||
*.bin
|
||||
*.map
|
||||
.gdb_config_bmp
|
||||
|
|
|
@ -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
i2c_eep/Makefile.f0
Normal file
38
i2c_eep/Makefile.f0
Normal 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
i2c_eep/Makefile.l0
Normal file
38
i2c_eep/Makefile.l0
Normal 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
i2c_eep/Makefile.l0btld
Normal file
29
i2c_eep/Makefile.l0btld
Normal 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
i2c_eep/i2c_eep.c
Normal file
201
i2c_eep/i2c_eep.c
Normal 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
i2c_eep/serial_helper.c
Normal file
39
i2c_eep/serial_helper.c
Normal 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
i2c_eep/serial_helper.h
Normal file
17
i2c_eep/serial_helper.h
Normal 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 */
|
|
@ -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…
Reference in a new issue