mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-11-03 22:08:28 +00:00 
			
		
		
		
	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:
		@@ -7,7 +7,8 @@ endif()
 | 
			
		||||
 | 
			
		||||
set(srcs "compare_set.c" "cpu_util.c")
 | 
			
		||||
if(NOT BOOTLOADER_BUILD)
 | 
			
		||||
    list(APPEND srcs "clk_ctrl_os.c")
 | 
			
		||||
    list(APPEND srcs "clk_ctrl_os.c"
 | 
			
		||||
                     "regi2c_ctrl.c")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
idf_component_register(SRCS ${srcs}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
COMPONENT_SRCDIRS := . port/$(IDF_TARGET)
 | 
			
		||||
COMPONENT_ADD_INCLUDEDIRS := . include port/$(IDF_TARGET)/private_include
 | 
			
		||||
COMPONENT_ADD_INCLUDEDIRS := . include include/soc port/$(IDF_TARGET)/ port/$(IDF_TARGET)/private_include
 | 
			
		||||
COMPONENT_ADD_LDFRAGMENTS := linker.lf
 | 
			
		||||
 | 
			
		||||
port/$(IDF_TARGET)/rtc_clk.o: CFLAGS += -fno-jump-tables -fno-tree-switch-conversion
 | 
			
		||||
 | 
			
		||||
ifdef IS_BOOTLOADER_BUILD
 | 
			
		||||
COMPONENT_OBJEXCLUDE += clk_ctrl_os.o
 | 
			
		||||
COMPONENT_OBJEXCLUDE += clk_ctrl_os.o regi2c_ctrl.o
 | 
			
		||||
endif
 | 
			
		||||
 
 | 
			
		||||
@@ -37,20 +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
 | 
			
		||||
 
 | 
			
		||||
@@ -64,20 +64,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_bbpll.h/regi2c_dig_reg.h/regi2c_lp_bias.h/regi2c_bias.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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -38,17 +38,42 @@ 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_bbpll.h/regi2c_dig_reg.h/regi2c_ulp.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)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										50
									
								
								components/esp_hw_support/regi2c_ctrl.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								components/esp_hw_support/regi2c_ctrl.c
									
									
									
									
									
										Normal 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);
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user