Skip to content

Commit

Permalink
component/esp32 : do more fix of dualcore bug
Browse files Browse the repository at this point in the history
1. the cache API in romcode will access DPORT register, so protect it.
2. fix STALL spelling.
3. check dport access by non-dport access function
  • Loading branch information
tianhaoesp committed May 12, 2017
1 parent c518325 commit 377a1f5
Show file tree
Hide file tree
Showing 7 changed files with 257 additions and 114 deletions.
4 changes: 2 additions & 2 deletions components/esp32/dport_access.c
Expand Up @@ -84,9 +84,9 @@ void IRAM_ATTR esp_dport_access_stall_other_cpu_start(void)
dport_access_end[cpu_id] = 0;

if (cpu_id == 0) {
WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_3_REG, DPORT_CPU_INTR_FROM_CPU_3); //interrupt on cpu1
_DPORT_REG_WRITE(DPORT_CPU_INTR_FROM_CPU_3_REG, DPORT_CPU_INTR_FROM_CPU_3); //interrupt on cpu1
} else {
WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_2_REG, DPORT_CPU_INTR_FROM_CPU_2); //interrupt on cpu0
_DPORT_REG_WRITE(DPORT_CPU_INTR_FROM_CPU_2_REG, DPORT_CPU_INTR_FROM_CPU_2); //interrupt on cpu0
}

while (!dport_access_start[cpu_id]) {};
Expand Down
37 changes: 37 additions & 0 deletions components/esp32/include/esp_assert.h
@@ -0,0 +1,37 @@
// Copyright 2015-2017 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.
#ifndef __ESP_ASSERT_H__
#define __ESP_ASSERT_H__

#include "assert.h"

/* Assert at compile time if possible, runtime otherwise */
#ifndef __cplusplus
/* __builtin_choose_expr() is only in C, makes this a lot cleaner */
#define TRY_STATIC_ASSERT(CONDITION, MSG) do { \
_Static_assert(__builtin_choose_expr(__builtin_constant_p(CONDITION), (CONDITION), 1), #MSG); \
assert(#MSG && (CONDITION)); \
} while(0)
#else
/* for C++, use __attribute__((error)) - works almost as well as _Static_assert */
#define TRY_STATIC_ASSERT(CONDITION, MSG) do { \
if (__builtin_constant_p(CONDITION) && !(CONDITION)) { \
extern __attribute__((error(#MSG))) void failed_compile_time_assert(void); \
failed_compile_time_assert(); \
} \
assert(#MSG && (CONDITION)); \
} while(0)
#endif /* __cplusplus */

#endif /* __ESP_ASSERT_H__ */
60 changes: 54 additions & 6 deletions components/esp32/include/rom/cache.h
Expand Up @@ -15,6 +15,8 @@
#ifndef _ROM_CACHE_H_
#define _ROM_CACHE_H_

#include "soc/dport_access.h"

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -64,7 +66,18 @@ void mmu_init(int cpu_no);
* 4 : mmu table to be written is out of range
* 5 : vaddr is out of range
*/
unsigned int cache_flash_mmu_set(int cpu_no, int pid, unsigned int vaddr, unsigned int paddr, int psize, int num);
static inline unsigned int IRAM_ATTR cache_flash_mmu_set(int cpu_no, int pid, unsigned int vaddr, unsigned int paddr, int psize, int num)
{
extern unsigned int cache_flash_mmu_set_rom(int cpu_no, int pid, unsigned int vaddr, unsigned int paddr, int psize, int num);

unsigned int ret;

DPORT_STALL_OTHER_CPU_START();
ret = cache_flash_mmu_set_rom(cpu_no, pid, vaddr, paddr, psize, num);
DPORT_STALL_OTHER_CPU_END();

return ret;
}

/**
* @brief Set Ext-SRAM-Cache mmu mapping.
Expand Down Expand Up @@ -93,7 +106,18 @@ unsigned int cache_flash_mmu_set(int cpu_no, int pid, unsigned int vaddr, unsign
* 4 : mmu table to be written is out of range
* 5 : vaddr is out of range
*/
unsigned int cache_sram_mmu_set(int cpu_no, int pid, unsigned int vaddr, unsigned int paddr, int psize, int num);
static inline unsigned int IRAM_ATTR cache_sram_mmu_set(int cpu_no, int pid, unsigned int vaddr, unsigned int paddr, int psize, int num)
{
extern unsigned int cache_sram_mmu_set_rom(int cpu_no, int pid, unsigned int vaddr, unsigned int paddr, int psize, int num);

unsigned int ret;

DPORT_STALL_OTHER_CPU_START();
ret = cache_sram_mmu_set_rom(cpu_no, pid, vaddr, paddr, psize, num);
DPORT_STALL_OTHER_CPU_END();

return ret;
}

/**
* @brief Initialise cache access for the cpu.
Expand All @@ -103,7 +127,13 @@ unsigned int cache_sram_mmu_set(int cpu_no, int pid, unsigned int vaddr, unsigne
*
* @return None
*/
void Cache_Read_Init(int cpu_no);
static inline void IRAM_ATTR Cache_Read_Init(int cpu_no)
{
extern void Cache_Read_Init_rom(int cpu_no);
DPORT_STALL_OTHER_CPU_START();
Cache_Read_Init_rom(cpu_no);
DPORT_STALL_OTHER_CPU_END();
}

/**
* @brief Flush the cache value for the cpu.
Expand All @@ -113,7 +143,13 @@ void Cache_Read_Init(int cpu_no);
*
* @return None
*/
void Cache_Flush(int cpu_no);
static inline void IRAM_ATTR Cache_Flush(int cpu_no)
{
extern void Cache_Flush_rom(int cpu_no);
DPORT_STALL_OTHER_CPU_START();
Cache_Flush_rom(cpu_no);
DPORT_STALL_OTHER_CPU_END();
}

/**
* @brief Disable Cache access for the cpu.
Expand All @@ -123,7 +159,13 @@ void Cache_Flush(int cpu_no);
*
* @return None
*/
void Cache_Read_Disable(int cpu_no);
static inline void IRAM_ATTR Cache_Read_Disable(int cpu_no)
{
extern void Cache_Read_Disable_rom(int cpu_no);
DPORT_STALL_OTHER_CPU_START();
Cache_Read_Disable_rom(cpu_no);
DPORT_STALL_OTHER_CPU_END();
}

/**
* @brief Enable Cache access for the cpu.
Expand All @@ -133,7 +175,13 @@ void Cache_Read_Disable(int cpu_no);
*
* @return None
*/
void Cache_Read_Enable(int cpu_no);
static inline void IRAM_ATTR Cache_Read_Enable(int cpu_no)
{
extern void Cache_Read_Enable_rom(int cpu_no);
DPORT_STALL_OTHER_CPU_START();
Cache_Read_Enable_rom(cpu_no);
DPORT_STALL_OTHER_CPU_END();
}

/**
* @}
Expand Down
12 changes: 6 additions & 6 deletions components/esp32/ld/esp32.rom.ld
Expand Up @@ -50,12 +50,12 @@ PROVIDE ( btdm_r_modules_func_p_set = 0x40054270 );
PROVIDE ( btdm_r_plf_func_p_set = 0x40054288 );
PROVIDE ( bt_util_buf_env = 0x3ffb8bd4 );
PROVIDE ( bzero = 0x4000c1f4 );
PROVIDE ( cache_flash_mmu_set = 0x400095e0 );
PROVIDE ( Cache_Flush = 0x40009a14 );
PROVIDE ( Cache_Read_Disable = 0x40009ab8 );
PROVIDE ( Cache_Read_Enable = 0x40009a84 );
PROVIDE ( Cache_Read_Init = 0x40009950 );
PROVIDE ( cache_sram_mmu_set = 0x400097f4 );
PROVIDE ( cache_flash_mmu_set_rom = 0x400095e0 );
PROVIDE ( Cache_Flush_rom = 0x40009a14 );
PROVIDE ( Cache_Read_Disable_rom = 0x40009ab8 );
PROVIDE ( Cache_Read_Enable_rom = 0x40009a84 );
PROVIDE ( Cache_Read_Init_rom = 0x40009950 );
PROVIDE ( cache_sram_mmu_set_rom = 0x400097f4 );
/* This is static function, but can be used, not generated by script*/
PROVIDE ( calc_rtc_memory_crc = 0x40008170 );
PROVIDE ( calloc = 0x4000bee4 );
Expand Down
4 changes: 2 additions & 2 deletions components/ethernet/emac_dev.c
Expand Up @@ -95,9 +95,9 @@ void emac_reset(void)
void emac_enable_clk(bool enable)
{
if (enable == true) {
REG_SET_BIT(EMAC_CLK_EN_REG, EMAC_CLK_EN);
DPORT_REG_SET_BIT(EMAC_CLK_EN_REG, EMAC_CLK_EN);
} else {
REG_CLR_BIT(EMAC_CLK_EN_REG, EMAC_CLK_EN);
DPORT_REG_CLR_BIT(EMAC_CLK_EN_REG, EMAC_CLK_EN);
}
}

Expand Down
39 changes: 19 additions & 20 deletions components/soc/esp32/include/soc/dport_access.h
Expand Up @@ -22,30 +22,29 @@ void esp_dport_access_stall_other_cpu_start(void);
void esp_dport_access_stall_other_cpu_end(void);

#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM)
#define DPORT_STAL_OTHER_CPU_START()
#define DPORT_STAL_OTHER_CPU_END()
#define DPORT_STALL_OTHER_CPU_START()
#define DPORT_STALL_OTHER_CPU_END()
#else
#define DPORT_STAL_OTHER_CPU_START() esp_dport_access_stall_other_cpu_start()
#define DPORT_STAL_OTHER_CPU_END() esp_dport_access_stall_other_cpu_end()
#define DPORT_STALL_OTHER_CPU_START() esp_dport_access_stall_other_cpu_start()
#define DPORT_STALL_OTHER_CPU_END() esp_dport_access_stall_other_cpu_end()
#endif

#define IS_DPORT_REG(_r) (((_r) >= DR_REG_DPORT_BASE) && (_r) <= DPORT_DATE_REG)

//Registers Operation {{
#define _REG_READ(_r) (*(volatile uint32_t *)(_r))
#define _REG_WRITE(_r, _v) (*(volatile uint32_t *)(_r)) = (_v)
//Origin access operation for the base and some special scene
#define _DPORT_REG_READ(_r) (*(volatile uint32_t *)(_r))
#define _DPORT_REG_WRITE(_r, _v) (*(volatile uint32_t *)(_r)) = (_v)

//write value to register
#define DPORT_REG_WRITE(_r, _v) _REG_WRITE(_r, _v)
#define DPORT_REG_WRITE(_r, _v) _DPORT_REG_WRITE(_r, _v)

//read value from register
inline uint32_t IRAM_ATTR DPORT_REG_READ(uint32_t reg)
static inline uint32_t IRAM_ATTR DPORT_REG_READ(uint32_t reg)
{
uint32_t val;

DPORT_STAL_OTHER_CPU_START();
val = _REG_READ(reg);
DPORT_STAL_OTHER_CPU_END();
DPORT_STALL_OTHER_CPU_START();
val = _DPORT_REG_READ(reg);
DPORT_STALL_OTHER_CPU_END();

return val;
}
Expand All @@ -54,19 +53,19 @@ inline uint32_t IRAM_ATTR DPORT_REG_READ(uint32_t reg)
#define DPORT_REG_GET_BIT(_r, _b) (DPORT_REG_READ(_r) & (_b))

//set bit or set bits to register
#define DPORT_REG_SET_BIT(_r, _b) (*(volatile uint32_t*)(_r) |= (_b))
#define DPORT_REG_SET_BIT(_r, _b) DPORT_REG_WRITE((_r), (DPORT_REG_READ(_r)|(_b)))

//clear bit or clear bits of register
#define DPORT_REG_CLR_BIT(_r, _b) (*(volatile uint32_t*)(_r) &= ~(_b))
#define DPORT_REG_CLR_BIT(_r, _b) DPORT_REG_WRITE((_r), (DPORT_REG_READ(_r) & (~(_b))))

//set bits of register controlled by mask
#define DPORT_REG_SET_BITS(_r, _b, _m) (*(volatile uint32_t*)(_r) = (DPORT_REG_READ(_r) & ~(_m)) | ((_b) & (_m)))
#define DPORT_REG_SET_BITS(_r, _b, _m) DPORT_REG_WRITE((_r), ((DPORT_REG_READ(_r) & (~(_m))) | ((_b) & (_m))))

//get field from register, uses field _S & _V to determine mask
#define DPORT_REG_GET_FIELD(_r, _f) ((DPORT_REG_READ(_r) >> (_f##_S)) & (_f##_V))

//set field to register, used when _f is not left shifted by _f##_S
#define DPORT_REG_SET_FIELD(_r, _f, _v) (DPORT_REG_WRITE((_r),((DPORT_REG_READ(_r) & ~((_f) << (_f##_S)))|(((_v) & (_f))<<(_f##_S)))))
#define DPORT_REG_SET_FIELD(_r, _f, _v) DPORT_REG_WRITE((_r), ((DPORT_REG_READ(_r) & (~((_f) << (_f##_S))))|(((_v) & (_f))<<(_f##_S))))

//get field value from a variable, used when _f is not left shifted by _f##_S
#define DPORT_VALUE_GET_FIELD(_r, _f) (((_r) >> (_f##_S)) & (_f))
Expand All @@ -90,13 +89,13 @@ inline uint32_t IRAM_ATTR DPORT_REG_READ(uint32_t reg)
#define _WRITE_PERI_REG(addr, val) (*((volatile uint32_t *)(addr))) = (uint32_t)(val)

//read value from register
inline uint32_t IRAM_ATTR DPORT_READ_PERI_REG(uint32_t addr)
static inline uint32_t IRAM_ATTR DPORT_READ_PERI_REG(uint32_t addr)
{
uint32_t val;

DPORT_STAL_OTHER_CPU_START();
DPORT_STALL_OTHER_CPU_START();
val = _READ_PERI_REG(addr);
DPORT_STAL_OTHER_CPU_END();
DPORT_STALL_OTHER_CPU_END();

return val;
}
Expand Down

0 comments on commit 377a1f5

Please sign in to comment.