regi2c: add a spinlock for accessing (reg)I2C devices

When not compiling bootloader, a spinlock will be used for reading or writing
I2C internal devices/registers.
When compiling for bootloader, no need to use any lock.
This commit is contained in:
Omar Chebib 2021-05-25 17:16:43 +08:00 committed by bot
parent ec196ae74b
commit d7687ce6fa
5 changed files with 158 additions and 49 deletions

View File

@ -1,6 +1,6 @@
idf_build_get_property(target IDF_TARGET)
idf_component_register(SRCS "src/cpu_util.c"
set(srcs "src/cpu_util.c"
"src/memory_layout_utils.c"
"src/lldesc.c"
"src/hal/cpu_hal.c"
@ -32,7 +32,13 @@ idf_component_register(SRCS "src/cpu_util.c"
"src/hal/wdt_hal_iram.c"
"src/compare_set.c"
"src/hal/twai_hal.c"
"src/hal/twai_hal_iram.c"
"src/hal/twai_hal_iram.c")
if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "src/regi2c_ctrl.c")
endif()
idf_component_register(SRCS ${srcs}
PRIV_REQUIRES ${target}
LDFRAGMENTS linker.lf)

View File

@ -12,3 +12,7 @@ COMPONENT_ADD_INCLUDEDIRS += include
-include $(COMPONENT_PATH)/soc/component.mk
COMPONENT_ADD_LDFRAGMENTS += linker.lf
ifdef IS_BOOTLOADER_BUILD
COMPONENT_OBJEXCLUDE += src/regi2c_ctrl.o
endif

View File

@ -37,21 +37,45 @@ uint8_t rom_i2c_readReg_Mask(uint8_t block, uint8_t host_id, uint8_t reg_add, ui
void rom_i2c_writeReg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data);
void rom_i2c_writeReg_Mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data);
#ifdef BOOTLOADER_BUILD
/**
* If compiling for the bootloader, ROM functions can be called directly,
* without the need of a lock.
*/
#define regi2c_ctrl_read_reg rom_i2c_readReg
#define regi2c_ctrl_read_reg_mask rom_i2c_readReg_Mask
#define regi2c_ctrl_write_reg rom_i2c_writeReg
#define regi2c_ctrl_write_reg_mask rom_i2c_writeReg_Mask
#else
#define i2c_read_reg_raw rom_i2c_readReg
#define i2c_read_reg_mask_raw rom_i2c_readReg_Mask
#define i2c_write_reg_raw rom_i2c_writeReg
#define i2c_write_reg_mask_raw rom_i2c_writeReg_Mask
uint8_t regi2c_ctrl_read_reg(uint8_t block, uint8_t host_id, uint8_t reg_add);
uint8_t regi2c_ctrl_read_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb);
void regi2c_ctrl_write_reg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data);
void regi2c_ctrl_write_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data);
#endif // BOOTLOADER_BUILD
/* Convenience macros for the above functions, these use register definitions
* from regi2c_apll.h/regi2c_bbpll.h header files.
*/
#define REGI2C_WRITE_MASK(block, reg_add, indata) \
rom_i2c_writeReg_Mask(block, block##_HOSTID, reg_add, reg_add##_MSB, reg_add##_LSB, indata)
regi2c_ctrl_write_reg_mask(block, block##_HOSTID, reg_add, reg_add##_MSB, reg_add##_LSB, indata)
#define REGI2C_READ_MASK(block, reg_add) \
rom_i2c_readReg_Mask(block, block##_HOSTID, reg_add, reg_add##_MSB, reg_add##_LSB)
regi2c_ctrl_read_reg_mask(block, block##_HOSTID, reg_add, reg_add##_MSB, reg_add##_LSB)
#define REGI2C_WRITE(block, reg_add, indata) \
rom_i2c_writeReg(block, block##_HOSTID, reg_add, indata)
regi2c_ctrl_write_reg(block, block##_HOSTID, reg_add, indata)
#define REGI2C_READ(block, reg_add) \
rom_i2c_readReg(block, block##_HOSTID, reg_add)
regi2c_ctrl_read_reg(block, block##_HOSTID, reg_add)
#ifdef __cplusplus
}

View File

@ -45,20 +45,45 @@ void i2c_rtc_write_reg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t
void i2c_rtc_write_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data);
void i2c_rtc_init(void);
#ifdef BOOTLOADER_BUILD
/**
* If compiling for the bootloader, internal functions can be called directly,
* without the need of a lock.
*/
#define regi2c_ctrl_read_reg i2c_rtc_read_reg
#define regi2c_ctrl_read_reg_mask i2c_rtc_read_reg_mask
#define regi2c_ctrl_write_reg i2c_rtc_write_reg
#define regi2c_ctrl_write_reg_mask i2c_rtc_write_reg_mask
#else
#define i2c_read_reg_raw i2c_rtc_read_reg
#define i2c_read_reg_mask_raw i2c_rtc_read_reg_mask
#define i2c_write_reg_raw i2c_rtc_write_reg
#define i2c_write_reg_mask_raw i2c_rtc_write_reg_mask
uint8_t regi2c_ctrl_read_reg(uint8_t block, uint8_t host_id, uint8_t reg_add);
uint8_t regi2c_ctrl_read_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb);
void regi2c_ctrl_write_reg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data);
void regi2c_ctrl_write_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data);
#endif // BOOTLOADER_BUILD
/* Convenience macros for the above functions, these use register definitions
* from regi2c_apll.h/regi2c_bbpll.h header files.
*/
#define REGI2C_WRITE_MASK(block, reg_add, indata) \
i2c_rtc_write_reg_mask(block, block##_HOSTID, reg_add, reg_add##_MSB, reg_add##_LSB, indata)
regi2c_ctrl_write_reg_mask(block, block##_HOSTID, reg_add, reg_add##_MSB, reg_add##_LSB, indata)
#define REGI2C_READ_MASK(block, reg_add) \
i2c_rtc_read_reg_mask(block, block##_HOSTID, reg_add, reg_add##_MSB, reg_add##_LSB)
regi2c_ctrl_read_reg_mask(block, block##_HOSTID, reg_add, reg_add##_MSB, reg_add##_LSB)
#define REGI2C_WRITE(block, reg_add, indata) \
i2c_rtc_write_reg(block, block##_HOSTID, reg_add, indata)
regi2c_ctrl_write_reg(block, block##_HOSTID, reg_add, indata)
#define REGI2C_READ(block, reg_add) \
i2c_rtc_read_reg(block, block##_HOSTID, reg_add)
regi2c_ctrl_read_reg(block, block##_HOSTID, reg_add)
#ifdef __cplusplus
}

View File

@ -0,0 +1,50 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "regi2c_ctrl.h"
#include <stdint.h>
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
static portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
uint8_t IRAM_ATTR regi2c_ctrl_read_reg(uint8_t block, uint8_t host_id, uint8_t reg_add)
{
portENTER_CRITICAL_ISR(&mux);
uint8_t value = i2c_read_reg_raw(block, host_id, reg_add);
portEXIT_CRITICAL_ISR(&mux);
return value;
}
uint8_t IRAM_ATTR regi2c_ctrl_read_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb)
{
portENTER_CRITICAL_ISR(&mux);
uint8_t value = i2c_read_reg_mask_raw(block, host_id, reg_add, msb, lsb);
portEXIT_CRITICAL_ISR(&mux);
return value;
}
void IRAM_ATTR regi2c_ctrl_write_reg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data)
{
portENTER_CRITICAL_ISR(&mux);
i2c_write_reg_raw(block, host_id, reg_add, data);
portEXIT_CRITICAL_ISR(&mux);
}
void IRAM_ATTR regi2c_ctrl_write_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data)
{
portENTER_CRITICAL_ISR(&mux);
i2c_write_reg_mask_raw(block, host_id, reg_add, msb, lsb, data);
portEXIT_CRITICAL_ISR(&mux);
}