xtensa/esp32: Fix cache issue detected by DEBUG_ASSERTION

This commit is contained in:
Alan C. Assis 2021-02-02 20:29:22 -03:00 committed by Abdelatif Guettouche
parent dbec1cf694
commit c4f87977dc
10 changed files with 415 additions and 82 deletions

View File

@ -118,6 +118,14 @@ CHIP_CSRCS += esp32_spi.c
endif
endif
# SPIFLASH and SPIRAM need spicache.c
ifeq ($(CONFIG_ESP32_SPIFLASH),y)
CHIP_CSRCS += esp32_spicache.c
else ifeq ($(CONFIG_ESP32_SPIRAM),y)
CHIP_CSRCS += esp32_spicache.c
endif
ifeq ($(CONFIG_ESP32_SPIFLASH),y)
CHIP_CSRCS += esp32_spiflash.c
endif

View File

@ -0,0 +1,140 @@
/****************************************************************************
* arch/xtensa/src/esp32/esp32_spicache.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_ESP32_SPIRAM) || defined(CONFIG_ESP32_SPIFLASH)
#include <stdint.h>
#include <debug.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/errno.h>
#include "xtensa.h"
#include "xtensa_attr.h"
#include "hardware/esp32_soc.h"
#include "hardware/esp32_spi.h"
#include "hardware/esp32_dport.h"
#ifdef CONFIG_ESP32_SPIRAM
#include "esp32_spiram.h"
#endif
#include "esp32_spicache.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: spiflash_disable_cache
****************************************************************************/
void IRAM_ATTR spi_disable_cache(int cpu, uint32_t *state)
{
const uint32_t cache_mask = 0x3f; /* Caches' bits in CTRL1_REG */
uint32_t regval;
uint32_t ret = 0;
if (cpu == 0)
{
ret |= (getreg32(DPORT_PRO_CACHE_CTRL1_REG) & cache_mask);
while (((getreg32(DPORT_PRO_DCACHE_DBUG0_REG) >>
DPORT_PRO_CACHE_STATE_S) & DPORT_PRO_CACHE_STATE) != 1)
{
;
}
regval = getreg32(DPORT_PRO_CACHE_CTRL_REG);
regval &= ~DPORT_PRO_CACHE_ENABLE_M;
putreg32(regval, DPORT_PRO_CACHE_CTRL_REG);
}
#ifdef CONFIG_SMP
else
{
ret |= (getreg32(DPORT_APP_CACHE_CTRL1_REG) & cache_mask);
while (((getreg32(DPORT_APP_DCACHE_DBUG0_REG) >>
DPORT_APP_CACHE_STATE_S) & DPORT_APP_CACHE_STATE) != 1)
{
;
}
regval = getreg32(DPORT_APP_CACHE_CTRL_REG);
regval &= ~DPORT_APP_CACHE_ENABLE_M;
putreg32(regval, DPORT_APP_CACHE_CTRL_REG);
}
#endif
*state = ret;
}
/****************************************************************************
* Name: spiflash_enable_cache
****************************************************************************/
void IRAM_ATTR spi_enable_cache(int cpu, uint32_t state)
{
const uint32_t cache_mask = 0x3f; /* Caches' bits in CTRL1_REG */
uint32_t regval;
uint32_t ctrlreg;
uint32_t ctrl1reg;
uint32_t ctrlmask;
if (cpu == 0)
{
ctrlreg = DPORT_PRO_CACHE_CTRL_REG;
ctrl1reg = DPORT_PRO_CACHE_CTRL1_REG;
ctrlmask = DPORT_PRO_CACHE_ENABLE_M;
}
#ifdef CONFIG_SMP
else
{
ctrlreg = DPORT_APP_CACHE_CTRL_REG;
ctrl1reg = DPORT_APP_CACHE_CTRL1_REG;
ctrlmask = DPORT_APP_CACHE_ENABLE_M;
}
#endif
regval = getreg32(ctrlreg);
regval |= ctrlmask;
putreg32(regval, ctrlreg);
regval = getreg32(ctrl1reg);
regval &= ~cache_mask;
regval |= state;
putreg32(regval, ctrl1reg);
}
#endif /* CONFIG_ESP32_SPICACHE */

View File

@ -0,0 +1,91 @@
/****************************************************************************
* arch/xtensa/src/esp32/esp32_spicache.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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 __ARCH_XTENSA_SRC_ESP32_ESP32_SPICACHE_H
#define __ARCH_XTENSA_SRC_ESP32_ESP32_SPICACHE_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <nuttx/mtd/mtd.h>
#include "xtensa_attr.h"
#ifndef __ASSEMBLY__
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: spi_disable_cache
*
* Description:
* Disable cache for SPI FLASH on a CPU
*
* Input Parameters:
* - cpu: ID of CPU to disable cache
* - state: pointer to cache reg state that will be returned
*
* Returned Value:
* None (the return will be over *state)
*
****************************************************************************/
void IRAM_ATTR spi_disable_cache(int cpu, uint32_t *state);
/****************************************************************************
* Name: spi_enable_cache
*
* Description:
* Enable cache for SPI FLASH on a CPU
*
* Input Parameters:
* - cpu: ID of CPU to enable cache
* - state: the cache reg state to be set
*
* Returned Value:
* None
*
****************************************************************************/
void IRAM_ATTR spi_enable_cache(int cpu, uint32_t state);
#ifdef __cplusplus
}
#endif
#undef EXTERN
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_SPICACHE_H */

View File

@ -51,6 +51,7 @@
#include "esp32_spiram.h"
#endif
#include "esp32_spicache.h"
#include "esp32_spiflash.h"
/****************************************************************************
@ -397,85 +398,6 @@ static inline void spi_reset_regbits(struct esp32_spiflash_s *priv,
putreg32(tmp & (~bits), priv->config->reg_base + offset);
}
/****************************************************************************
* Name: spiflash_disable_cache
****************************************************************************/
static void IRAM_ATTR spi_disable_cache(int cpu, uint32_t *state)
{
const uint32_t cache_mask = 0x3f; /* Caches' bits in CTRL1_REG */
uint32_t regval;
uint32_t ret = 0;
if (cpu == 0)
{
ret |= (getreg32(DPORT_PRO_CACHE_CTRL1_REG) & cache_mask);
while (((getreg32(DPORT_PRO_DCACHE_DBUG0_REG) >>
DPORT_PRO_CACHE_STATE_S) & DPORT_PRO_CACHE_STATE) != 1)
{
;
}
regval = getreg32(DPORT_PRO_CACHE_CTRL_REG);
regval &= ~DPORT_PRO_CACHE_ENABLE_M;
putreg32(regval, DPORT_PRO_CACHE_CTRL_REG);
}
#ifdef CONFIG_SMP
else
{
ret |= (getreg32(DPORT_APP_CACHE_CTRL1_REG) & cache_mask);
while (((getreg32(DPORT_APP_DCACHE_DBUG0_REG) >>
DPORT_APP_CACHE_STATE_S) & DPORT_APP_CACHE_STATE) != 1)
{
;
}
regval = getreg32(DPORT_APP_CACHE_CTRL_REG);
regval &= ~DPORT_APP_CACHE_ENABLE_M;
putreg32(regval, DPORT_APP_CACHE_CTRL_REG);
}
#endif
*state = ret;
}
/****************************************************************************
* Name: spiflash_enable_cache
****************************************************************************/
static void IRAM_ATTR spi_enable_cache(int cpu, uint32_t state)
{
const uint32_t cache_mask = 0x3f; /* Caches' bits in CTRL1_REG */
uint32_t regval;
uint32_t ctrlreg;
uint32_t ctrl1reg;
uint32_t ctrlmask;
if (cpu == 0)
{
ctrlreg = DPORT_PRO_CACHE_CTRL_REG;
ctrl1reg = DPORT_PRO_CACHE_CTRL1_REG;
ctrlmask = DPORT_PRO_CACHE_ENABLE_M;
}
#ifdef CONFIG_SMP
else
{
ctrlreg = DPORT_APP_CACHE_CTRL_REG;
ctrl1reg = DPORT_APP_CACHE_CTRL1_REG;
ctrlmask = DPORT_APP_CACHE_ENABLE_M;
}
#endif
regval = getreg32(ctrlreg);
regval |= ctrlmask;
putreg32(regval, ctrlreg);
regval = getreg32(ctrl1reg);
regval &= ~cache_mask;
regval |= state;
putreg32(regval, ctrl1reg);
}
/****************************************************************************
* Name: esp32_spiflash_opstart
*

View File

@ -31,6 +31,8 @@
#include <stdint.h>
#include <nuttx/mtd/mtd.h>
#include "xtensa_attr.h"
#ifndef __ASSEMBLY__
#undef EXTERN

View File

@ -33,8 +33,10 @@
#include <string.h>
#include <sys/param.h>
#include <nuttx/config.h>
#include <nuttx/irq.h>
#include "esp32_spiram.h"
#include "esp32_spicache.h"
#include "esp32_psram.h"
#include "xtensa.h"
#include "xtensa_attr.h"
@ -97,6 +99,138 @@ size_t __attribute__((weak)) esp_himem_reserved_area_size(void)
* Public Functions
****************************************************************************/
unsigned int IRAM_ATTR cache_sram_mmu_set(int cpu_no, int pid,
unsigned int vaddr,
unsigned int paddr,
int psize, int num)
{
uint32_t regval;
uint32_t statecpu0;
#ifdef CONFIG_SMP
uint32_t statecpu1;
#endif
unsigned int i;
unsigned int shift;
unsigned int mask_s;
unsigned int mmu_addr;
unsigned int mmu_table_val;
irqstate_t flags;
/* address check */
if ((ADDRESS_CHECK(vaddr, psize)) || (ADDRESS_CHECK(paddr, psize)))
{
return MMU_SET_ADDR_ALIGNED_ERROR;
}
/* psize check */
if (psize == 32)
{
shift = 15;
mask_s = 0;
}
else if (psize == 16)
{
shift = 14;
mask_s = 1;
}
else if (psize == 8)
{
shift = 13;
mask_s = 2;
}
else if (psize == 4)
{
shift = 12;
mask_s = 3;
}
else if (psize == 2)
{
shift = 11;
mask_s = 4;
}
else
{
return MMU_SET_PAGE_SIZE_ERROR;
}
/* mmu value */
mmu_table_val = paddr >> shift;
/* mmu_addr */
if (pid == 0 || pid == 1)
{
if (vaddr >= PRO_DRAM1_START_ADDR && vaddr < PRO_DRAM1_END_ADDR(psize))
{
mmu_addr = 1152 + ((vaddr & (0x3fffff >> mask_s)) >> shift);
}
else
{
return MMU_SET_VADDR_OUT_RANGE;
}
}
else
{
if (vaddr >= PRO_DRAM1_START_ADDR && vaddr < PRO_DRAM1_END_ADDR(psize))
{
mmu_addr = (1024 + (pid << 7)) +
((vaddr & (0x3fffff >> mask_s)) >> shift);
}
else
{
return MMU_SET_VADDR_OUT_RANGE;
}
}
/* The MMU registers are implemented in such a way that lookups from the
* cache subsystem may collide with CPU access to the MMU registers. We use
* the flash guards to make sure the cache is disabled.
*/
flags = spin_lock_irqsave();
spi_disable_cache(0, &statecpu0);
#ifdef CONFIG_SMP
spi_disable_cache(1, &statecpu1);
#endif
/* mmu change */
for (i = 0; i < num; i++)
{
*(volatile unsigned int *)(CACHE_MMU_ADDRESS_BASE(cpu_no) +
mmu_addr * 4) = mmu_table_val + i; /* write table */
mmu_addr++;
}
if (cpu_no == 0)
{
regval = getreg32(DPORT_PRO_CACHE_CTRL1_REG);
regval &= ~DPORT_PRO_CMMU_SRAM_PAGE_MODE;
regval |= mask_s;
putreg32(regval, DPORT_PRO_CACHE_CTRL1_REG);
}
else
{
regval = getreg32(DPORT_APP_CACHE_CTRL1_REG);
regval &= ~DPORT_APP_CMMU_SRAM_PAGE_MODE;
regval |= mask_s;
putreg32(regval, DPORT_APP_CACHE_CTRL1_REG);
}
spi_enable_cache(0, statecpu0);
#ifdef CONFIG_SMP
spi_enable_cache(1, statecpu1);
#endif
spin_unlock_irqrestore(flags);
return 0;
}
void IRAM_ATTR esp_spiram_init_cache(void)
{
#ifdef CONFIG_SMP

View File

@ -35,6 +35,45 @@
#define ESP_SPIRAM_SIZE_64MBITS 2 /* SPI RAM size is 64 MBits */
#define ESP_SPIRAM_SIZE_INVALID 3 /* SPI RAM size is invalid */
/* Errors that can be returned by cache_sram_* */
#define MMU_SET_ADDR_ALIGNED_ERROR 1
#define MMU_SET_PAGE_SIZE_ERROR 3
#define MMU_SET_VADDR_OUT_RANGE 5
#define PROCACHE_MMU_ADDR_BASE 0x3FF10000
#define APPCACHE_MMU_ADDR_BASE 0x3FF12000
/* sram address */
#define PRO_DRAM1_START_ADDR 0x3F800000
#define PRO_DRAM1_END_ADDR(psize) (PRO_DRAM1_START_ADDR + ((psize) << 17))
/* cache mmu register file address */
#define CACHE_MMU_ADDRESS_BASE(cpu_no) ((cpu_no) ? (APPCACHE_MMU_ADDR_BASE) :\
(PROCACHE_MMU_ADDR_BASE))
/* virtual address, physical address check */
#define ADDRESS_CHECK(addr,psize) (((addr) & (0xFFFF >>((64/(psize))-1))) != 0)
/* CPU number check */
#define CPU_NUMBER_CHECK(cpu_no) (((cpu_no)<0) || ((cpu_no)>1))
/* PID check */
#define PID_CHECK(pid) (((pid)<0) || ((pid)>7))
/* flash MMU edge check (flash size default : 16*1024 K) */
#define FLASH_MMU_EDGE_CHECK(mmu_val,num) (((mmu_val) + (num)) > 256)
/* sram MMU edge check (sram size default : 8*1024 K) */
#define SRAM_MMU_EDGE_CHECK(mmu_val,num,psize) (((mmu_val) + (num)) > ((8*1024)/(psize)))
/* Description: get SPI RAM size
* return
* - ESP_SPIRAM_SIZE_INVALID if SPI RAM not enabled or not valid

View File

@ -64,7 +64,6 @@ 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 );
/* This is static function, but can be used, not generated by script*/
PROVIDE ( calc_rtc_memory_crc = 0x40008170 );
PROVIDE ( calloc = 0x4000bee4 );

View File

@ -64,7 +64,6 @@ 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 );
/* This is static function, but can be used, not generated by script*/
PROVIDE ( calc_rtc_memory_crc = 0x40008170 );
PROVIDE ( calloc = 0x4000bee4 );

View File

@ -64,7 +64,6 @@ 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 );
/* This is static function, but can be used, not generated by script*/
PROVIDE ( calc_rtc_memory_crc = 0x40008170 );
PROVIDE ( calloc = 0x4000bee4 );