2021-06-22 11:28:01 +08:00

657 lines
22 KiB
C

// 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.
#pragma once
#include "hal/assert.h"
#ifdef __cplusplus
extern "C" {
#endif
// not implemented for esp32s3 yet
#if 0
/**
* === IRAM0 ====
*/
#define IRAM0_TOTAL_UNI_BLOCKS 4
#define IRAM0_UNI_BLOCK_0 0
#define IRAM0_UNI_BLOCK_1 1
#define IRAM0_UNI_BLOCK_2 2
#define IRAM0_UNI_BLOCK_3 3
#define IRAM0_SPL_BLOCK_BASE 0x40000000
//unified management (SRAM blocks 0-3)
#define IRAM0_UNI_BLOCK_0_LOW 0x40020000
#define IRAM0_UNI_BLOCK_0_HIGH 0x40021FFF
#define IRAM0_UNI_BLOCK_1_LOW 0x40022000
#define IRAM0_UNI_BLOCK_1_HIGH 0x40023FFF
#define IRAM0_UNI_BLOCK_2_LOW 0x40024000
#define IRAM0_UNI_BLOCK_2_HIGH 0x40025FFF
#define IRAM0_UNI_BLOCK_3_LOW 0x40026000
#define IRAM0_UNI_BLOCK_3_HIGH 0x40027FFF
//split management (SRAM blocks 4-21)
#define IRAM0_SPL_BLOCK_LOW 0x40028000 //block 4 low
#define IRAM0_SPL_BLOCK_HIGH 0x4006FFFF //block 21 high
#define IRAM0_SPLTADDR_MIN 0x40030000 //block 6 low - minimum splitting address
//IRAM0 interrupt status bitmasks
#define IRAM0_INTR_ST_FAULTADDR_M 0x003FFFFC //(bits 21:6 in the reg, as well as in real address)
#define IRAM0_INTR_ST_FAULTADDR_HI 0x40000000 //(high nonsignificant bits 31:22 of the faulting address - constant)
#define IRAM0_INTR_ST_OP_TYPE_BIT BIT(1) //instruction: 0, data: 1
#define IRAM0_INTR_ST_OP_RW_BIT BIT(0) //read: 0, write: 1
static inline uint32_t esp_memprot_iram0_get_intr_source_num(void)
{
return ETS_PMS_PRO_IRAM0_ILG_INTR_SOURCE;
}
static inline void esp_memprot_iram0_intr_ena(bool enable)
{
if ( enable ) {
DPORT_SET_PERI_REG_MASK( DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_EN );
} else {
DPORT_CLEAR_PERI_REG_MASK( DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_EN );
}
}
static inline uint32_t esp_memprot_iram0_get_ena_reg(void)
{
return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_4_REG);
}
static inline uint32_t esp_memprot_iram0_get_fault_reg(void)
{
return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_5_REG);
}
static inline void esp_memprot_iram0_get_fault_status(uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype)
{
uint32_t status_bits = esp_memprot_iram0_get_fault_reg();
uint32_t fault_addr = (status_bits & IRAM0_INTR_ST_FAULTADDR_M);
*faulting_address = (uint32_t *)(fault_addr | IRAM0_INTR_ST_FAULTADDR_HI);
*op_type = (uint32_t)status_bits & IRAM0_INTR_ST_OP_RW_BIT;
*op_subtype = (uint32_t)status_bits & IRAM0_INTR_ST_OP_TYPE_BIT;
}
static inline bool esp_memprot_iram0_is_assoc_intr(void)
{
return DPORT_GET_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_INTR) > 0;
}
static inline void esp_memprot_iram0_clear_intr(void)
{
DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_CLR);
}
static inline uint32_t esp_memprot_iram0_get_intr_ena_bit(void)
{
return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_EN);
}
static inline uint32_t esp_memprot_iram0_get_intr_on_bit(void)
{
return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_INTR);
}
static inline uint32_t esp_memprot_iram0_get_intr_clr_bit(void)
{
return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_CLR);
}
//resets automatically on CPU restart
static inline void esp_memprot_iram0_set_lock(void)
{
DPORT_WRITE_PERI_REG( DPORT_PMS_PRO_IRAM0_0_REG, DPORT_PMS_PRO_IRAM0_LOCK);
}
static inline uint32_t esp_memprot_iram0_get_lock_reg(void)
{
return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_0_REG);
}
static inline uint32_t esp_memprot_iram0_get_lock_bit(void)
{
return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_0_REG, DPORT_PMS_PRO_IRAM0_LOCK);
}
//block 0-3
static inline void esp_memprot_iram0_set_uni_block_perm(uint32_t block, bool write_perm, bool read_perm, bool exec_perm)
{
HAL_ASSERT(block < IRAM0_TOTAL_UNI_BLOCKS);
uint32_t write_bit, read_bit, exec_bit;
switch ( block ) {
case IRAM0_UNI_BLOCK_0:
write_bit = DPORT_PMS_PRO_IRAM0_SRAM_0_W;
read_bit = DPORT_PMS_PRO_IRAM0_SRAM_0_R;
exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_0_F;
break;
case IRAM0_UNI_BLOCK_1:
write_bit = DPORT_PMS_PRO_IRAM0_SRAM_1_W;
read_bit = DPORT_PMS_PRO_IRAM0_SRAM_1_R;
exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_1_F;
break;
case IRAM0_UNI_BLOCK_2:
write_bit = DPORT_PMS_PRO_IRAM0_SRAM_2_W;
read_bit = DPORT_PMS_PRO_IRAM0_SRAM_2_R;
exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_2_F;
break;
case IRAM0_UNI_BLOCK_3:
write_bit = DPORT_PMS_PRO_IRAM0_SRAM_3_W;
read_bit = DPORT_PMS_PRO_IRAM0_SRAM_3_R;
exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_3_F;
break;
default:
abort();
}
if ( write_perm ) {
DPORT_SET_PERI_REG_MASK( DPORT_PMS_PRO_IRAM0_1_REG, write_bit );
} else {
DPORT_CLEAR_PERI_REG_MASK( DPORT_PMS_PRO_IRAM0_1_REG, write_bit );
}
if ( read_perm ) {
DPORT_SET_PERI_REG_MASK( DPORT_PMS_PRO_IRAM0_1_REG, read_bit );
} else {
DPORT_CLEAR_PERI_REG_MASK( DPORT_PMS_PRO_IRAM0_1_REG, read_bit );
}
if ( exec_perm ) {
DPORT_SET_PERI_REG_MASK( DPORT_PMS_PRO_IRAM0_1_REG, exec_bit );
} else {
DPORT_CLEAR_PERI_REG_MASK( DPORT_PMS_PRO_IRAM0_1_REG, exec_bit );
}
}
static inline uint32_t esp_memprot_iram0_get_uni_block_read_bit(uint32_t block)
{
HAL_ASSERT(block < IRAM0_TOTAL_UNI_BLOCKS);
switch ( block ) {
case IRAM0_UNI_BLOCK_0:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_R );
case IRAM0_UNI_BLOCK_1:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_R );
case IRAM0_UNI_BLOCK_2:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_R );
case IRAM0_UNI_BLOCK_3:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_R );
default:
abort();
}
}
static inline uint32_t esp_memprot_iram0_get_uni_block_write_bit(uint32_t block)
{
HAL_ASSERT(block < IRAM0_TOTAL_UNI_BLOCKS);
switch ( block ) {
case IRAM0_UNI_BLOCK_0:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_W );
case IRAM0_UNI_BLOCK_1:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_W );
case IRAM0_UNI_BLOCK_2:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_W );
case IRAM0_UNI_BLOCK_3:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_W );
default:
abort();
}
}
static inline uint32_t esp_memprot_iram0_get_uni_block_exec_bit(uint32_t block)
{
HAL_ASSERT(block < IRAM0_TOTAL_UNI_BLOCKS);
switch ( block ) {
case IRAM0_UNI_BLOCK_0:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_F );
case IRAM0_UNI_BLOCK_1:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_F );
case IRAM0_UNI_BLOCK_2:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_F );
case IRAM0_UNI_BLOCK_3:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_F );
default:
abort();
}
}
static inline void esp_memprot_iram0_get_uni_block_sgnf_bits(uint32_t block, uint32_t *write_bit, uint32_t *read_bit, uint32_t *exec_bit)
{
HAL_ASSERT(block < IRAM0_TOTAL_UNI_BLOCKS);
switch ( block ) {
case IRAM0_UNI_BLOCK_0:
*write_bit = DPORT_PMS_PRO_IRAM0_SRAM_0_W;
*read_bit = DPORT_PMS_PRO_IRAM0_SRAM_0_R;
*exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_0_F;
break;
case IRAM0_UNI_BLOCK_1:
*write_bit = DPORT_PMS_PRO_IRAM0_SRAM_1_W;
*read_bit = DPORT_PMS_PRO_IRAM0_SRAM_1_R;
*exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_1_F;
break;
case IRAM0_UNI_BLOCK_2:
*write_bit = DPORT_PMS_PRO_IRAM0_SRAM_2_W;
*read_bit = DPORT_PMS_PRO_IRAM0_SRAM_2_R;
*exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_2_F;
break;
case IRAM0_UNI_BLOCK_3:
*write_bit = DPORT_PMS_PRO_IRAM0_SRAM_3_W;
*read_bit = DPORT_PMS_PRO_IRAM0_SRAM_3_R;
*exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_3_F;
break;
default:
abort();
}
}
static inline uint32_t esp_memprot_iram0_get_perm_uni_reg(void)
{
return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_1_REG);
}
static inline uint32_t esp_memprot_iram0_get_perm_split_reg(void)
{
return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_2_REG);
}
static inline void esp_memprot_iram0_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx)
{
uint32_t addr = (uint32_t)split_addr;
HAL_ASSERT(addr <= IRAM0_SPL_BLOCK_HIGH);
//find possible split.address in low region blocks
int uni_blocks_low = -1;
if ( addr >= IRAM0_UNI_BLOCK_0_LOW ) {
uni_blocks_low++;
}
if ( addr >= IRAM0_UNI_BLOCK_1_LOW ) {
uni_blocks_low++;
}
if ( addr >= IRAM0_UNI_BLOCK_2_LOW ) {
uni_blocks_low++;
}
if ( addr >= IRAM0_UNI_BLOCK_3_LOW ) {
uni_blocks_low++;
}
//unified mgmt settings per block (bits W/R/X: [11:9] bl3, [8:6] bl2, [5:3] bl1, [2:0] bl0)
uint32_t write_bit, read_bit, exec_bit;
uint32_t uni_block_perm = 0;
for ( size_t x = 0; x < IRAM0_TOTAL_UNI_BLOCKS; x++ ) {
esp_memprot_iram0_get_uni_block_sgnf_bits(x, &write_bit, &read_bit, &exec_bit);
if ( x <= uni_blocks_low ) {
if (lw) {
uni_block_perm |= write_bit;
}
if (lr) {
uni_block_perm |= read_bit;
}
if (lx) {
uni_block_perm |= exec_bit;
}
} else {
if (hw) {
uni_block_perm |= write_bit;
}
if (hr) {
uni_block_perm |= read_bit;
}
if (hx) {
uni_block_perm |= exec_bit;
}
}
}
//if splt.ddr not set yet, do required normalization to make the addr writeble into splt.mgmt cfg register
uint32_t reg_split_addr = 0;
if ( addr >= IRAM0_SPL_BLOCK_LOW ) {
//split Address must be WORD aligned
reg_split_addr = addr >> 2;
HAL_ASSERT(addr == (reg_split_addr << 2));
//use only 17 signf.bits as the cropped parts are constant for whole section (bits [16:0])
reg_split_addr = (reg_split_addr << DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR_S) & DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR_M;
}
//prepare high & low permission mask (bits: [22:20] high range, [19:17] low range)
uint32_t permission_mask = 0;
if ( lw ) {
permission_mask |= DPORT_PMS_PRO_IRAM0_SRAM_4_L_W;
}
if ( lr ) {
permission_mask |= DPORT_PMS_PRO_IRAM0_SRAM_4_L_R;
}
if ( lx ) {
permission_mask |= DPORT_PMS_PRO_IRAM0_SRAM_4_L_F;
}
if ( hw ) {
permission_mask |= DPORT_PMS_PRO_IRAM0_SRAM_4_H_W;
}
if ( hr ) {
permission_mask |= DPORT_PMS_PRO_IRAM0_SRAM_4_H_R;
}
if ( hx ) {
permission_mask |= DPORT_PMS_PRO_IRAM0_SRAM_4_H_F;
}
//write both cfg. registers
DPORT_WRITE_PERI_REG( DPORT_PMS_PRO_IRAM0_1_REG, uni_block_perm );
DPORT_WRITE_PERI_REG( DPORT_PMS_PRO_IRAM0_2_REG, reg_split_addr | permission_mask );
}
static inline void esp_memprot_iram0_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx)
{
*lw = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_W );
*lr = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_R );
*lx = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_F );
*hw = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_H_W );
*hr = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_H_R );
*hx = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_H_F );
}
/**
* === DRAM0 ====
*/
#define DRAM0_TOTAL_UNI_BLOCKS 4
#define DRAM0_UNI_BLOCK_0 0
#define DRAM0_UNI_BLOCK_1 1
#define DRAM0_UNI_BLOCK_2 2
#define DRAM0_UNI_BLOCK_3 3
#define DRAM0_SPL_BLOCK_BASE 0x3FFB0000
//unified management (SRAM blocks 0-3)
#define DRAM0_UNI_BLOCK_0_LOW 0x3FFB0000
#define DRAM0_UNI_BLOCK_0_HIGH 0x3FFB1FFF
#define DRAM0_UNI_BLOCK_1_LOW 0x3FFB2000
#define DRAM0_UNI_BLOCK_1_HIGH 0x3FFB3FFF
#define DRAM0_UNI_BLOCK_2_LOW 0x3FFB4000
#define DRAM0_UNI_BLOCK_2_HIGH 0x3FFB5FFF
#define DRAM0_UNI_BLOCK_3_LOW 0x3FFB6000
#define DRAM0_UNI_BLOCK_3_HIGH 0x3FFB7FFF
//split management (SRAM blocks 4-21)
#define DRAM0_SPL_BLOCK_LOW 0x3FFB8000 //block 4 low
#define DRAM0_SPL_BLOCK_HIGH 0x3FFFFFFF //block 21 high
#define DRAM0_SPLTADDR_MIN 0x3FFC0000 //block 6 low - minimum splitting address
//DRAM0 interrupt status bitmasks
#define DRAM0_INTR_ST_FAULTADDR_M 0x03FFFFC0 //(bits 25:6 in the reg)
#define DRAM0_INTR_ST_FAULTADDR_S 0x4 //(bits 21:2 of real address)
#define DRAM0_INTR_ST_FAULTADDR_HI 0x3FF00000 //(high nonsignificant bits 31:22 of the faulting address - constant)
#define DRAM0_INTR_ST_OP_RW_BIT BIT(4) //read: 0, write: 1
#define DRAM0_INTR_ST_OP_ATOMIC_BIT BIT(5) //non-atomic: 0, atomic: 1
static inline uint32_t esp_memprot_dram0_get_intr_source_num(void)
{
return ETS_PMS_PRO_DRAM0_ILG_INTR_SOURCE;
}
static inline void esp_memprot_dram0_intr_ena(bool enable)
{
if ( enable ) {
DPORT_SET_PERI_REG_MASK( DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_EN );
} else {
DPORT_CLEAR_PERI_REG_MASK( DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_EN );
}
}
static inline bool esp_memprot_dram0_is_assoc_intr(void)
{
return DPORT_GET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_INTR) > 0;
}
static inline void esp_memprot_dram0_clear_intr(void)
{
DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_CLR);
}
static inline uint32_t esp_memprot_dram0_get_intr_ena_bit(void)
{
return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_EN);
}
static inline uint32_t esp_memprot_dram0_get_intr_on_bit(void)
{
return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_INTR);
}
static inline uint32_t esp_memprot_dram0_get_intr_clr_bit(void)
{
return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_CLR);
}
static inline uint32_t esp_memprot_dram0_get_lock_bit(void)
{
return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_0_REG, DPORT_PMS_PRO_DRAM0_LOCK);
}
static inline void esp_memprot_dram0_get_uni_block_sgnf_bits(uint32_t block, uint32_t *write_bit, uint32_t *read_bit)
{
HAL_ASSERT(block < DRAM0_TOTAL_UNI_BLOCKS);
switch ( block ) {
case DRAM0_UNI_BLOCK_0:
*write_bit = DPORT_PMS_PRO_DRAM0_SRAM_0_W;
*read_bit = DPORT_PMS_PRO_DRAM0_SRAM_0_R;
break;
case DRAM0_UNI_BLOCK_1:
*write_bit = DPORT_PMS_PRO_DRAM0_SRAM_1_W;
*read_bit = DPORT_PMS_PRO_DRAM0_SRAM_1_R;
break;
case DRAM0_UNI_BLOCK_2:
*write_bit = DPORT_PMS_PRO_DRAM0_SRAM_2_W;
*read_bit = DPORT_PMS_PRO_DRAM0_SRAM_2_R;
break;
case DRAM0_UNI_BLOCK_3:
*write_bit = DPORT_PMS_PRO_DRAM0_SRAM_3_W;
*read_bit = DPORT_PMS_PRO_DRAM0_SRAM_3_R;
break;
default:
abort();
}
}
static inline void esp_memprot_dram0_set_uni_block_perm(uint32_t block, bool write_perm, bool read_perm)
{
HAL_ASSERT(block < DRAM0_TOTAL_UNI_BLOCKS);
uint32_t write_bit, read_bit;
esp_memprot_dram0_get_uni_block_sgnf_bits(block, &write_bit, &read_bit);
if ( write_perm ) {
DPORT_SET_PERI_REG_MASK( DPORT_PMS_PRO_DRAM0_1_REG, write_bit );
} else {
DPORT_CLEAR_PERI_REG_MASK( DPORT_PMS_PRO_DRAM0_1_REG, write_bit );
}
if ( read_perm ) {
DPORT_SET_PERI_REG_MASK( DPORT_PMS_PRO_DRAM0_1_REG, read_bit );
} else {
DPORT_CLEAR_PERI_REG_MASK( DPORT_PMS_PRO_DRAM0_1_REG, read_bit );
}
}
static inline uint32_t esp_memprot_dram0_get_uni_block_read_bit(uint32_t block)
{
HAL_ASSERT(block < DRAM0_TOTAL_UNI_BLOCKS);
switch ( block ) {
case DRAM0_UNI_BLOCK_0:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_0_R );
case DRAM0_UNI_BLOCK_1:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_1_R );
case DRAM0_UNI_BLOCK_2:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_2_R );
case DRAM0_UNI_BLOCK_3:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_3_R );
default:
abort();
}
}
static inline uint32_t esp_memprot_dram0_get_uni_block_write_bit(uint32_t block)
{
HAL_ASSERT(block < DRAM0_TOTAL_UNI_BLOCKS);
switch ( block ) {
case DRAM0_UNI_BLOCK_0:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_0_W );
case DRAM0_UNI_BLOCK_1:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_1_W );
case DRAM0_UNI_BLOCK_2:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_2_W );
case DRAM0_UNI_BLOCK_3:
return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_3_W );
default:
abort();
}
}
static inline uint32_t esp_memprot_dram0_get_lock_reg(void)
{
return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_0_REG);
}
//lock resets automatically on CPU restart
static inline void esp_memprot_dram0_set_lock(void)
{
DPORT_WRITE_PERI_REG( DPORT_PMS_PRO_DRAM0_0_REG, DPORT_PMS_PRO_DRAM0_LOCK);
}
static inline uint32_t esp_memprot_dram0_get_perm_reg(void)
{
return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_1_REG);
}
static inline uint32_t esp_memprot_dram0_get_ena_reg(void)
{
return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_3_REG);
}
static inline uint32_t esp_memprot_dram0_get_fault_reg(void)
{
return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_4_REG);
}
static inline void esp_memprot_dram0_get_fault_status(uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype)
{
uint32_t status_bits = esp_memprot_dram0_get_fault_reg();
uint32_t fault_addr = (status_bits & DRAM0_INTR_ST_FAULTADDR_M) >> DRAM0_INTR_ST_FAULTADDR_S;
*faulting_address = (uint32_t *)(fault_addr | DRAM0_INTR_ST_FAULTADDR_HI);
*op_type = (uint32_t)status_bits & DRAM0_INTR_ST_OP_RW_BIT;
*op_subtype = (uint32_t)status_bits & DRAM0_INTR_ST_OP_ATOMIC_BIT;
}
static inline void esp_memprot_dram0_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr)
{
uint32_t addr = (uint32_t)split_addr;
//low boundary check provided by LD script. see comment in esp_memprot_iram0_set_prot()
HAL_ASSERT(addr <= DRAM0_SPL_BLOCK_HIGH);
//set low region
int uni_blocks_low = -1;
if ( addr >= DRAM0_UNI_BLOCK_0_LOW ) {
uni_blocks_low++;
}
if ( addr >= DRAM0_UNI_BLOCK_1_LOW ) {
uni_blocks_low++;
}
if ( addr >= DRAM0_UNI_BLOCK_2_LOW ) {
uni_blocks_low++;
}
if ( addr >= DRAM0_UNI_BLOCK_3_LOW ) {
uni_blocks_low++;
}
//set unified mgmt region
uint32_t write_bit, read_bit, uni_block_perm = 0;
for ( size_t x = 0; x < DRAM0_TOTAL_UNI_BLOCKS; x++ ) {
esp_memprot_dram0_get_uni_block_sgnf_bits(x, &write_bit, &read_bit);
if ( x <= uni_blocks_low ) {
if (lw) {
uni_block_perm |= write_bit;
}
if (lr) {
uni_block_perm |= read_bit;
}
} else {
if (hw) {
uni_block_perm |= write_bit;
}
if (hr) {
uni_block_perm |= read_bit;
}
}
}
//check split address is WORD aligned
uint32_t reg_split_addr = addr >> 2;
HAL_ASSERT(addr == (reg_split_addr << 2));
//shift aligned split address to proper bit offset
reg_split_addr = (reg_split_addr << DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR_S) & DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR_M;
//prepare high & low permission mask
uint32_t permission_mask = 0;
if (lw) {
permission_mask |= DPORT_PMS_PRO_DRAM0_SRAM_4_L_W;
}
if (lr) {
permission_mask |= DPORT_PMS_PRO_DRAM0_SRAM_4_L_R;
}
if (hw) {
permission_mask |= DPORT_PMS_PRO_DRAM0_SRAM_4_H_W;
}
if (hr) {
permission_mask |= DPORT_PMS_PRO_DRAM0_SRAM_4_H_R;
}
//write configuration to DPORT_PMS_PRO_DRAM0_1_REG
DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_DRAM0_1_REG, reg_split_addr | permission_mask | uni_block_perm);
}
static inline void esp_memprot_dram0_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr)
{
*lw = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_L_W );
*lr = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_L_R );
*hw = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_H_W );
*hr = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_H_R );
}
#endif
#ifdef __cplusplus
}
#endif