i2c: Initial stub import of old f4 code
Currently (despite docs) is an import of code reading the onboard i2c peripheral
This commit is contained in:
parent
3a79a3b923
commit
115b771e56
3 changed files with 246 additions and 0 deletions
40
tests/i2c-master/Makefile.stm32f4-disco
Normal file
40
tests/i2c-master/Makefile.stm32f4-disco
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
BOARD = stm32f4-disco
|
||||
PROJECT = i2c-master-$(BOARD)
|
||||
BUILD_DIR = bin-$(BOARD)
|
||||
|
||||
SHARED_DIR = ../../shared
|
||||
|
||||
CFILES = main-$(BOARD).c
|
||||
#CFILES += adc-power.c
|
||||
CFILES += trace.c trace_stdio.c
|
||||
|
||||
VPATH += $(SHARED_DIR)
|
||||
|
||||
INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR))
|
||||
|
||||
OPENCM3_DIR=../../libopencm3/
|
||||
|
||||
### This section can go to an arch shared rules eventually...
|
||||
DEVICE=stm32f405xg
|
||||
#OOCD_INTERFACE = stlink-v2
|
||||
#OOCD_TARGET = stm32f4x
|
||||
OOCD_FILE = ../../openocd/openocd.stm32f4-disco.cfg
|
||||
|
||||
include ../../rules.mk
|
||||
17
tests/i2c-master/README.md
Normal file
17
tests/i2c-master/README.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
i2c master mode tests.
|
||||
|
||||
While many of the disco boards have some form of i2c device onboard,
|
||||
which would, on the face of it, make testing easy, it's a different
|
||||
device on each board, and there are boards without it.
|
||||
|
||||
Instead, use a known I2C peripheral on all boards, and require/expect
|
||||
a known fixed i2c slave device. (Eventually, this will be a soft
|
||||
controllable i2c slave in the auto test setup ;)
|
||||
|
||||
Debug is via SWO wherever possible, PA2 (tx only) on less capable cores
|
||||
|
||||
Pinouts:
|
||||
|
||||
board SCLK SDA
|
||||
f4-disco PB8 PB9 i2c1
|
||||
|
||||
189
tests/i2c-master/main-stm32f4-disco.c
Normal file
189
tests/i2c-master/main-stm32f4-disco.c
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* Feb 2017 Karl Palsson <karlp@tweak.net.au>
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/i2c.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
#define LED_DISCO_GREEN_PORT GPIOD
|
||||
#define LED_DISCO_GREEN_PIN GPIO12
|
||||
|
||||
#define CODEC_ADDRESS 0x4a
|
||||
|
||||
|
||||
static void codec_gpio_init(void)
|
||||
{
|
||||
/* reset pin */
|
||||
rcc_periph_clock_enable(RCC_GPIOD);
|
||||
gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO4);
|
||||
|
||||
/* i2c control lines */
|
||||
rcc_periph_clock_enable(RCC_GPIOB);
|
||||
gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO6 | GPIO9);
|
||||
gpio_set_output_options(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO6 | GPIO9);
|
||||
gpio_set_af(GPIOB, GPIO_AF4, GPIO6 | GPIO9);
|
||||
}
|
||||
|
||||
static void codec_i2c_init(void)
|
||||
{
|
||||
rcc_periph_clock_enable(RCC_I2C1);
|
||||
i2c_peripheral_disable(I2C1);
|
||||
i2c_reset(I2C1);
|
||||
i2c_set_standard_mode(I2C1);
|
||||
i2c_enable_ack(I2C1);
|
||||
i2c_set_dutycycle(I2C1, I2C_CCR_DUTY_DIV2); /* default, no need to do this really */
|
||||
i2c_set_clock_frequency(I2C1, I2C_CR2_FREQ_42MHZ);
|
||||
/* 42MHz / (100kHz * 2) */
|
||||
i2c_set_ccr(I2C1, 210);
|
||||
/* standard mode, freqMhz+1*/
|
||||
i2c_set_trise(I2C1, 43);
|
||||
i2c_peripheral_enable(I2C1);
|
||||
}
|
||||
|
||||
static void codec_init(void)
|
||||
{
|
||||
int i;
|
||||
/* Configure the Codec related IOs */
|
||||
codec_gpio_init();
|
||||
|
||||
/* reset the codec */
|
||||
gpio_clear(GPIOD, GPIO4);
|
||||
for (i = 0; i < 1000000; i++) { /* Wait a bit. */
|
||||
__asm__("NOP");
|
||||
}
|
||||
gpio_set(GPIOD, GPIO4);
|
||||
|
||||
codec_i2c_init();
|
||||
}
|
||||
|
||||
static int codec_write_reg(uint8_t reg, uint8_t val)
|
||||
{
|
||||
uint32_t i2c = I2C1;
|
||||
|
||||
while ((I2C_SR2(i2c) & I2C_SR2_BUSY)) {
|
||||
}
|
||||
|
||||
i2c_send_start(i2c);
|
||||
|
||||
/* Wait for master mode selected */
|
||||
while (!((I2C_SR1(i2c) & I2C_SR1_SB)
|
||||
& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));
|
||||
|
||||
i2c_send_7bit_address(i2c, CODEC_ADDRESS, I2C_WRITE);
|
||||
|
||||
/* Waiting for address is transferred. */
|
||||
while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));
|
||||
|
||||
/* Cleaning ADDR condition sequence. */
|
||||
uint32_t reg32 = I2C_SR2(i2c);
|
||||
(void) reg32; /* unused */
|
||||
|
||||
/* Common above here */
|
||||
|
||||
/* Sending the data. */
|
||||
i2c_send_data(i2c, reg);
|
||||
while (!(I2C_SR1(i2c) & (I2C_SR1_BTF)));
|
||||
i2c_send_data(i2c, val);
|
||||
while (!(I2C_SR1(i2c) & (I2C_SR1_BTF | I2C_SR1_TxE)));
|
||||
|
||||
/* Send STOP condition. */
|
||||
i2c_send_stop(i2c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t codec_read_reg(uint8_t reg)
|
||||
{
|
||||
uint32_t i2c = I2C1;
|
||||
|
||||
while ((I2C_SR2(i2c) & I2C_SR2_BUSY)) {
|
||||
}
|
||||
|
||||
i2c_send_start(i2c);
|
||||
|
||||
/* Wait for master mode selected */
|
||||
while (!((I2C_SR1(i2c) & I2C_SR1_SB)
|
||||
& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));
|
||||
|
||||
i2c_send_7bit_address(i2c, CODEC_ADDRESS, I2C_WRITE);
|
||||
|
||||
/* Waiting for address is transferred. */
|
||||
while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));
|
||||
|
||||
/* Cleaning ADDR condition sequence. */
|
||||
uint32_t reg32 = I2C_SR2(i2c);
|
||||
(void) reg32; /* unused */
|
||||
|
||||
/* Common stuff ABOVE HERE */
|
||||
|
||||
i2c_send_data(i2c, reg);
|
||||
while (!(I2C_SR1(i2c) & (I2C_SR1_BTF)));
|
||||
|
||||
i2c_send_start(i2c);
|
||||
|
||||
/* Wait for master mode selected */
|
||||
while (!((I2C_SR1(i2c) & I2C_SR1_SB)
|
||||
& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));
|
||||
|
||||
i2c_send_7bit_address(i2c, CODEC_ADDRESS, I2C_READ);
|
||||
|
||||
/* Waiting for address is transferred. */
|
||||
while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));
|
||||
|
||||
i2c_disable_ack(i2c);
|
||||
|
||||
/* Cleaning ADDR condition sequence. */
|
||||
reg32 = I2C_SR2(i2c);
|
||||
(void) reg32; /* unused */
|
||||
|
||||
i2c_send_stop(i2c);
|
||||
|
||||
while (!(I2C_SR1(i2c) & I2C_SR1_RxNE));
|
||||
uint32_t result = i2c_get_data(i2c);
|
||||
|
||||
i2c_enable_ack(i2c);
|
||||
I2C_SR1(i2c) &= ~I2C_SR1_AF;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void codec_readid(void)
|
||||
{
|
||||
uint8_t res = codec_read_reg(0x01);
|
||||
printf("raw res = %#x Codec is %#x (should be 0x1c), revision %d\n", res, res >> 3, res & 0x7);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i, j;
|
||||
rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
|
||||
/* green led for ticking */
|
||||
rcc_periph_clock_enable(RCC_GPIOD);
|
||||
gpio_mode_setup(LED_DISCO_GREEN_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,
|
||||
LED_DISCO_GREEN_PIN);
|
||||
printf("hi guys!\n");
|
||||
codec_init();
|
||||
codec_readid();
|
||||
|
||||
codec_write_reg(0x14, 0xff);
|
||||
for (i = 0; i < 8; i++) {
|
||||
uint8_t pass_vol_a = codec_read_reg(0x14);
|
||||
printf("Passthrough vol A was: %#x\n", pass_vol_a);
|
||||
codec_write_reg(0x14, pass_vol_a >> 1);
|
||||
gpio_toggle(LED_DISCO_GREEN_PORT, LED_DISCO_GREEN_PIN);
|
||||
for (j = 0; j < 100000; j++) { /* Wait a bit. */
|
||||
__asm__("NOP");
|
||||
}
|
||||
}
|
||||
|
||||
/* Nothing else to do */;
|
||||
while (1) {
|
||||
;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue