Skip to content

Commit

Permalink
Add initial code.
Browse files Browse the repository at this point in the history
  • Loading branch information
amitesh-singh committed Jan 7, 2018
1 parent 90ae2de commit 16a3816
Show file tree
Hide file tree
Showing 6 changed files with 333 additions and 0 deletions.
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# i2c slave based on stm32
This is an i2c slave based on stm32. This implements a simple math calculator
for doing addition, subtraction and multiplication of given two numbers.

## how to compile

Modify `meson.build` according to your needs.

`libocm3Path` - libopencm3 directory path

You need to issue `./build.sh` for once.
```shell
$ ./build.sh
$ cd builddir
```
ninja - generates elf file.
```shell
$ ninja
```

ninja hex - generates hex file.
```shell
$ ninja hex
```
ninja size - gives the summary of hex file size.
```shell
$ ninja size
```
ninja upload - upload hex file to stm32 via stlink programmer.
```shell
$ ninja upload
```

Refer to [my blog](http://amitesh-singh.github.io/stm32/2018/01/07/making-i2c-slave-using-stm32f103.html) for more details.
1 change: 1 addition & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
meson . builddir --cross-file cross-file.txt --buildtype=minsize
19 changes: 19 additions & 0 deletions cross-file.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[binaries]
c = 'arm-none-eabi-gcc'
cpp = 'arm-none-eabi-g++'
ar = 'arm-none-eabi-ar'
strip = 'arm-none-eabi-strip'
objcopy = 'arm-none-eabi-objcopy'
size = 'arm-none-eabi-size'

[host_machine]
system = 'linux'
cpu_family = 'x86_64'
cpu = 'x64'
endian = 'little'

[target_machine]
system = 'bare-metel'
cpu_family = 'stm32'
cpu = 'STM32F1'
endian = 'little'
8 changes: 8 additions & 0 deletions libopencm3_f1.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
}

INCLUDE libopencm3_stm32f1.ld

157 changes: 157 additions & 0 deletions main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
* math calculator i2c slave stm32
* Copyright (C) 2017 Amitesh Singh <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

extern "C"
{
#include <libopencm3/cm3/common.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/i2c.h>
#include <libopencm3/cm3/nvic.h>
}

static void
my_delay_1( void )
{
int i = 72e6/2/4;

while( i > 0 )
{
i--;
__asm__( "nop" );
}
}

#define MYSLAVE_ADDRESS 0x32
//Set Commands
#define MYSLAVE_SET_REG 0x01
//GET commands
#define MYSLAVE_GET_ADD_RESULT 0x02
#define MYSLAVE_GET_SUB_RESULT 0x03
#define MYSLAVE_GET_MUL_RESULT 0x04

static void
i2c_slave_init(uint8_t ownaddress)
{
rcc_periph_clock_enable(RCC_GPIOB);
rcc_periph_clock_enable(RCC_I2C1);

nvic_enable_irq(NVIC_I2C1_EV_IRQ);

// configure i2c pins
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN,
GPIO_I2C1_SDA); //PB7
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN,
GPIO_I2C1_SCL); //PB6

i2c_reset(I2C1);
i2c_peripheral_disable(I2C1);

i2c_set_speed(I2C1, i2c_speed_sm_100k, I2C_CR2_FREQ_36MHZ);
i2c_set_own_7bit_slave_address(I2C1, ownaddress);
i2c_enable_interrupt(I2C1, I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN);
i2c_peripheral_enable(I2C1);

// slave needs to acknowledge on receiving bytes
// set it after enabling Peripheral i.e. PE = 1
i2c_enable_ack(I2C1);
}

volatile uint8_t *read_p;
volatile uint8_t *write_p;
volatile uint8_t writing;
volatile uint8_t reading;

volatile uint8_t buf[3];
volatile uint16_t val;

//i2c1 event ISR
extern "C" void i2c1_ev_isr(void)
{
uint32_t sr1, sr2;

sr1 = I2C_SR1(I2C1);

if (sr1 & I2C_SR1_ADDR)
{
reading = 0;
read_p = buf;
write_p = ((volatile uint8_t *)(&val) + 1);
writing = 2;
//Clear the ADDR sequence by reading SR2.
sr2 = I2C_SR2(I2C1);
(void) sr2;
}
else if (sr1 & I2C_SR1_RxNE)
{
//ignore more than 3 bytes reading
if (reading > 3)
return;
//read bytes from slave
*read_p++ = i2c_get_data(I2C1);
reading++;
}
else if ((sr1 & I2C_SR1_TxE) && !(sr1 & I2C_SR1_BTF))
{
//send data to master in MSB order
i2c_send_data(I2C1, *write_p--);
writing--;
}
// done by master by sending STOP
//this event happens when slave is in Recv mode at the end of communication
else if (sr1 & I2C_SR1_STOPF)
{
i2c_peripheral_enable(I2C1);

if (buf[0] == MYSLAVE_GET_ADD_RESULT)
val = buf[1] + buf[2];
else if (buf[0] == MYSLAVE_GET_SUB_RESULT)
val = buf[1] - buf[2];
else if (buf[0] == MYSLAVE_GET_MUL_RESULT)
val = buf[1] * buf[2];
}
//this event happens when slave is in transmit mode at the end of communication
else if (sr1 & I2C_SR1_AF)
{
//(void) I2C_SR1(I2C1);
I2C_SR1(I2C1) &= ~(I2C_SR1_AF);
}
}

int main( void )
{
//set STM32 to 72 MHz
rcc_clock_setup_in_hse_8mhz_out_72mhz();

// Enable GPIOC clock
rcc_periph_clock_enable(RCC_GPIOC);
//Set GPIO13 (inbuild led connected) to 'output push-pull'
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL,
GPIO13);
//switch led off
gpio_set(GPIOC, GPIO13);

//initialize i2c slave
i2c_slave_init(MYSLAVE_ADDRESS);

while( 1 )
{
gpio_toggle(GPIOC, GPIO13);
my_delay_1();
}
}
114 changes: 114 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#
# stm32-libopencm3-meson build
# Copyright (C) 2017 Amitesh Singh
#
# 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 2.1 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/>.
#


project('stm32f1-project', 'cpp')

compiler_obj = meson.get_compiler('cpp')

size = find_program('arm-none-eabi-size')
objcopy = find_program('arm-none-eabi-objcopy')
stinfo = find_program('st-info')
stflash = find_program('st-flash')

#define libopencm3 path here
libocm3Path = '/home/ami/repos/libopencm3'

#define cpu types here
cputype = 'cortex-m3'
cpudefine = 'STM32F1'
libocm3cputype = 'opencm3_stm32f1'

#Add your source files here
srcfiles = ['main.cpp']


libocm3IncPath = libocm3Path + '/include'
libocm3LibPath = libocm3Path + '/lib'

# check for libopencm3 library
libocm3lib_obj = compiler_obj.find_library(libocm3cputype, required: true, dirs: libocm3LibPath)
if libocm3lib_obj.found() == true
message('Found libopencm3 library at ' + libocm3Path)
else
error('unable to find libopencm3 library')
endif

incdir = include_directories(libocm3IncPath)

stm32f1cargs = ['-Os',
'-ggdb',
'-mcpu=' + cputype,
'-mthumb',
'-msoft-float',
'-std=gnu++14',
'-Wall',
'-Wshadow',
'-ffunction-sections',
'-fdata-sections',
'-D' + cpudefine,
'-fno-exceptions',
#'-I' + libocm3IncPath
]

stm32f1linkargs = ['-Os',
'-ggdb',
'-D' + cpudefine,
'-fdata-sections',
'-mcpu=' + cputype,
'-mthumb',
'-msoft-float',
'-lc',
'-flto',
#'-T../libopencm3_f1.ld',
'-T' + meson.current_source_dir() + '/libopencm3_f1.ld',
'--specs=nosys.specs',
'-nostartfiles',
'-Wl,--gc-sections',
'-L' + libocm3LibPath,
# '-l' + libocm3cputype,
]

p = ['blink', srcfiles, stm32f1cargs, stm32f1linkargs]

exe = executable(p[0], p[1],
cpp_args: p[2],
link_args: p[3],
include_directories : incdir,
dependencies: libocm3lib_obj,
build_by_default: true)

run_target('hex', command: [objcopy, ['-Obinary', exe.full_path(),
exe.full_path() + '.hex']], depends: exe)
run_target('size', command: [size, exe.full_path(), '-B'], depends: exe)

# STlink programmer related commands
run_target('probe', command: [stinfo, '--probe'])
run_target('upload', command: [stflash, 'write', exe.full_path() + '.hex', '0x08000000'], depends: exe)

if meson.is_cross_build()
message('cross compiling for ' + cputype)
message(' \n ninja - generates elf file.
ninja hex - generates hex file.
ninja upload - upload hex file to stm32 via stlink programmer.
ninja probe - probe stlink programmer.
ninja size - gives the summary of hex file size.
(C) Amitesh Singh ')
endif

0 comments on commit 16a3816

Please sign in to comment.