From 16a381651574111cfa775a6a8ed4931da3b99d3f Mon Sep 17 00:00:00 2001 From: Amitesh Singh Date: Sun, 7 Jan 2018 20:20:37 +0900 Subject: [PATCH] Add initial code. --- README.md | 34 ++++++++++ build.sh | 1 + cross-file.txt | 19 ++++++ libopencm3_f1.ld | 8 +++ main.cpp | 157 +++++++++++++++++++++++++++++++++++++++++++++++ meson.build | 114 ++++++++++++++++++++++++++++++++++ 6 files changed, 333 insertions(+) create mode 100644 README.md create mode 100755 build.sh create mode 100644 cross-file.txt create mode 100644 libopencm3_f1.ld create mode 100644 main.cpp create mode 100644 meson.build diff --git a/README.md b/README.md new file mode 100644 index 0000000..cedd81c --- /dev/null +++ b/README.md @@ -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. diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..14a8e32 --- /dev/null +++ b/build.sh @@ -0,0 +1 @@ +meson . builddir --cross-file cross-file.txt --buildtype=minsize diff --git a/cross-file.txt b/cross-file.txt new file mode 100644 index 0000000..0c20e46 --- /dev/null +++ b/cross-file.txt @@ -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' diff --git a/libopencm3_f1.ld b/libopencm3_f1.ld new file mode 100644 index 0000000..ed8e230 --- /dev/null +++ b/libopencm3_f1.ld @@ -0,0 +1,8 @@ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (xrw) : ORIGIN = 0x20000000, LENGTH = 20K +} + +INCLUDE libopencm3_stm32f1.ld + diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..d32a197 --- /dev/null +++ b/main.cpp @@ -0,0 +1,157 @@ +/* + * math calculator i2c slave stm32 + * Copyright (C) 2017 Amitesh Singh + * + * 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 . + */ + +extern "C" +{ + #include + #include + #include + #include + #include +} + +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(); + } +} diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..7ec00fa --- /dev/null +++ b/meson.build @@ -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 . + # + + +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 +