mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
532 lines
17 KiB
C
532 lines
17 KiB
C
/*
|
|
* Copyright (C) 2023-2024 OpenMV, LLC.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* 3. Any redistribution, use, or modification in source or binary form
|
|
* is done solely for personal benefit and not for any commercial
|
|
* purpose or for monetary gain. For commercial licensing options,
|
|
* please contact openmv@openmv.io
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE LICENSOR AND COPYRIGHT OWNER "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR OR COPYRIGHT
|
|
* OWNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* Alif HAL.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
|
|
#include "irq.h"
|
|
#include CMSIS_MCU_H
|
|
|
|
#include "py/mphal.h"
|
|
#include "alif_hal.h"
|
|
#include "sys_ctrl_i3c.h"
|
|
#include "sys_ctrl_spi.h"
|
|
#include "sys_ctrl_cpi.h"
|
|
#include "sys_ctrl_pdm.h"
|
|
#include "se_services.h"
|
|
#include "omv_boardconfig.h"
|
|
// Define pin objects in this file.
|
|
#define OMV_GPIO_DEFINE_PINS (1)
|
|
#include "omv_gpio.h"
|
|
|
|
#define MPU_ATTR_NORMAL_WT_RA_TRANSIENT (0)
|
|
#define MPU_ATTR_DEVICE_nGnRE (1)
|
|
#define MPU_ATTR_NORMAL_WB_RA_WA (2)
|
|
#define MPU_ATTR_NORMAL_WT_RA (3)
|
|
#define MPU_ATTR_NORMAL_NON_CACHEABLE (4)
|
|
|
|
#define MPU_REGION_SRAM0 (0)
|
|
#define MPU_REGION_SRAM1 (1)
|
|
#define MPU_REGION_HOST_PERIPHERALS (2)
|
|
#define MPU_REGION_MRAM (3)
|
|
#define MPU_REGION_OSPI_REGISTERS (4)
|
|
#define MPU_REGION_OSPI0_XIP (5)
|
|
#define MPU_REGION_OSPI1_XIP (6)
|
|
#define MPU_REGION_OPENAMP (7)
|
|
#define MPU_REGION_FIRST_FREE (MPU_REGION_OPENAMP + 1)
|
|
|
|
uint8_t OMV_BOARD_UID_ADDR[12];
|
|
|
|
void alif_hal_mpu_init(void);
|
|
extern int alif_npu_init(void);
|
|
extern void __fatal_error(const char *msg);
|
|
|
|
void alif_hal_init(void) {
|
|
// Disable BOR.
|
|
ANA_REG->VBAT_ANA_REG1 |= (1 << 25);
|
|
|
|
// Disable USB mux.
|
|
#if CORE_M55_HP && defined(OMV_USB_SWITCH_PIN)
|
|
omv_gpio_config(OMV_USB_SWITCH_PIN, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_LOW, -1);
|
|
omv_gpio_write(OMV_USB_SWITCH_PIN, 1);
|
|
#endif
|
|
|
|
// Init services.
|
|
se_services_init();
|
|
|
|
// Configures run/off profiles and SRAM clock source.
|
|
board_early_init();
|
|
|
|
// Set board unique ID.
|
|
se_services_get_unique_id(OMV_BOARD_UID_ADDR);
|
|
// To match the USB serial.
|
|
for (size_t i = 0, j = sizeof(OMV_BOARD_UID_ADDR) - 1; i < j; i++, j--) {
|
|
OMV_BOARD_UID_ADDR[i] ^= OMV_BOARD_UID_ADDR[j];
|
|
OMV_BOARD_UID_ADDR[j] ^= OMV_BOARD_UID_ADDR[i];
|
|
OMV_BOARD_UID_ADDR[i] ^= OMV_BOARD_UID_ADDR[j];
|
|
}
|
|
|
|
// load MPU regions and enable the MPU.
|
|
alif_hal_mpu_init();
|
|
|
|
// Configure and initialize the NPU.
|
|
alif_npu_init();
|
|
|
|
// Configure and enable USB IRQs.
|
|
NVIC_ClearPendingIRQ(USB_IRQ_IRQn);
|
|
NVIC_SetPriority(USB_IRQ_IRQn, IRQ_PRI_USB);
|
|
|
|
#if MICROPY_PY_CSI
|
|
// Enable CSI clock and configure pins.
|
|
alif_hal_csi_init(OMV_CSI_BASE);
|
|
#endif
|
|
}
|
|
|
|
int alif_hal_i2c_init(uint32_t bus_id) {
|
|
omv_gpio_t scl_pin = NULL;
|
|
omv_gpio_t sda_pin = NULL;
|
|
|
|
switch (bus_id) {
|
|
#if defined(OMV_I3C0_ID)
|
|
case OMV_I3C0_ID: {
|
|
enable_i3c_clock();
|
|
scl_pin = OMV_I3C0_SCL_PIN;
|
|
sda_pin = OMV_I3C0_SDA_PIN;
|
|
break;
|
|
}
|
|
#endif
|
|
#if defined(OMV_I2C0_ID)
|
|
case OMV_I2C0_ID: {
|
|
scl_pin = OMV_I2C0_SCL_PIN;
|
|
sda_pin = OMV_I2C0_SDA_PIN;
|
|
break;
|
|
}
|
|
#endif
|
|
#if defined(OMV_I2C1_ID)
|
|
case OMV_I2C1_ID: {
|
|
scl_pin = OMV_I2C1_SCL_PIN;
|
|
sda_pin = OMV_I2C1_SDA_PIN;
|
|
break;
|
|
}
|
|
#endif
|
|
#if defined(OMV_I2C2_ID)
|
|
case OMV_I2C2_ID: {
|
|
scl_pin = OMV_I2C2_SCL_PIN;
|
|
sda_pin = OMV_I2C2_SDA_PIN;
|
|
break;
|
|
}
|
|
#endif
|
|
#if defined(OMV_I2C3_ID)
|
|
case OMV_I2C3_ID: {
|
|
scl_pin = OMV_I2C3_SCL_PIN;
|
|
sda_pin = OMV_I2C3_SDA_PIN;
|
|
break;
|
|
}
|
|
#endif
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
omv_gpio_config(scl_pin, OMV_GPIO_MODE_ALT_OD, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_LOW, -1);
|
|
omv_gpio_config(sda_pin, OMV_GPIO_MODE_ALT_OD, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_LOW, -1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int alif_hal_spi_init(uint32_t bus_id, bool nss_enable, uint32_t nss_pol) {
|
|
typedef struct {
|
|
omv_gpio_t sclk_pin;
|
|
omv_gpio_t miso_pin;
|
|
omv_gpio_t mosi_pin;
|
|
omv_gpio_t ssel_pin;
|
|
} spi_pins_t;
|
|
|
|
spi_pins_t spi_pins = { NULL, NULL, NULL, NULL };
|
|
|
|
switch (bus_id) {
|
|
#if defined(OMV_SPI0_ID)
|
|
case OMV_SPI0_ID: {
|
|
spi_pins = (spi_pins_t) {
|
|
OMV_SPI0_SCLK_PIN, OMV_SPI0_MISO_PIN, OMV_SPI0_MOSI_PIN, OMV_SPI0_SSEL_PIN
|
|
};
|
|
break;
|
|
}
|
|
#endif
|
|
#if defined(OMV_SPI1_ID)
|
|
case OMV_SPI1_ID: {
|
|
spi_pins = (spi_pins_t) {
|
|
OMV_SPI1_SCLK_PIN, OMV_SPI1_MISO_PIN, OMV_SPI1_MOSI_PIN, OMV_SPI1_SSEL_PIN
|
|
};
|
|
break;
|
|
}
|
|
#endif
|
|
#if defined(OMV_SPI2_ID)
|
|
case OMV_SPI2_ID: {
|
|
spi_pins = (spi_pins_t) {
|
|
OMV_SPI2_SCLK_PIN, OMV_SPI2_MISO_PIN, OMV_SPI2_MOSI_PIN, OMV_SPI2_SSEL_PIN
|
|
};
|
|
break;
|
|
}
|
|
#endif
|
|
#if defined(OMV_SPI3_ID)
|
|
case OMV_SPI3_ID: {
|
|
spi_pins = (spi_pins_t) {
|
|
OMV_SPI3_SCLK_PIN, OMV_SPI3_MISO_PIN, OMV_SPI3_MOSI_PIN, OMV_SPI3_SSEL_PIN
|
|
};
|
|
break;
|
|
}
|
|
#endif
|
|
#if defined(OMV_SPI4_ID)
|
|
case OMV_SPI4_ID: {
|
|
spi_pins = (spi_pins_t) {
|
|
OMV_SPI4_SCLK_PIN, OMV_SPI4_MISO_PIN, OMV_SPI4_MOSI_PIN, OMV_SPI4_SSEL_PIN
|
|
};
|
|
enable_lpspi_clk();
|
|
break;
|
|
}
|
|
#endif
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
omv_gpio_config(spi_pins.sclk_pin, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_MED, -1);
|
|
omv_gpio_config(spi_pins.miso_pin, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_MED, -1);
|
|
omv_gpio_config(spi_pins.mosi_pin, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_MED, -1);
|
|
if (nss_enable) {
|
|
omv_gpio_config(spi_pins.ssel_pin, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_MED, -1);
|
|
} else {
|
|
omv_gpio_config(spi_pins.ssel_pin, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_MED, 0);
|
|
if (nss_pol == OMV_SPI_NSS_LOW) {
|
|
omv_gpio_write(spi_pins.ssel_pin, 1);
|
|
} else {
|
|
omv_gpio_write(spi_pins.ssel_pin, 0);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int alif_hal_spi_deinit(uint32_t bus_id) {
|
|
typedef struct {
|
|
omv_gpio_t sclk_pin;
|
|
omv_gpio_t miso_pin;
|
|
omv_gpio_t mosi_pin;
|
|
omv_gpio_t ssel_pin;
|
|
} spi_pins_t;
|
|
|
|
spi_pins_t spi_pins = { NULL, NULL, NULL, NULL };
|
|
|
|
switch (bus_id) {
|
|
#if defined(OMV_SPI0_ID)
|
|
case OMV_SPI0_ID: {
|
|
spi_pins = (spi_pins_t) {
|
|
OMV_SPI0_SCLK_PIN, OMV_SPI0_MISO_PIN, OMV_SPI0_MOSI_PIN, OMV_SPI0_SSEL_PIN
|
|
};
|
|
break;
|
|
}
|
|
#endif
|
|
#if defined(OMV_SPI1_ID)
|
|
case OMV_SPI1_ID: {
|
|
spi_pins = (spi_pins_t) {
|
|
OMV_SPI1_SCLK_PIN, OMV_SPI1_MISO_PIN, OMV_SPI1_MOSI_PIN, OMV_SPI1_SSEL_PIN
|
|
};
|
|
break;
|
|
}
|
|
#endif
|
|
#if defined(OMV_SPI2_ID)
|
|
case OMV_SPI2_ID: {
|
|
spi_pins = (spi_pins_t) {
|
|
OMV_SPI2_SCLK_PIN, OMV_SPI2_MISO_PIN, OMV_SPI2_MOSI_PIN, OMV_SPI2_SSEL_PIN
|
|
};
|
|
break;
|
|
}
|
|
#endif
|
|
#if defined(OMV_SPI3_ID)
|
|
case OMV_SPI3_ID: {
|
|
spi_pins = (spi_pins_t) {
|
|
OMV_SPI3_SCLK_PIN, OMV_SPI3_MISO_PIN, OMV_SPI3_MOSI_PIN, OMV_SPI3_SSEL_PIN
|
|
};
|
|
break;
|
|
}
|
|
#endif
|
|
#if defined(OMV_SPI4_ID)
|
|
case OMV_SPI4_ID: {
|
|
spi_pins = (spi_pins_t) {
|
|
OMV_SPI4_SCLK_PIN, OMV_SPI4_MISO_PIN, OMV_SPI4_MOSI_PIN, OMV_SPI4_SSEL_PIN
|
|
};
|
|
disable_lpspi_clk();
|
|
break;
|
|
}
|
|
#endif
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
omv_gpio_deinit(spi_pins.sclk_pin);
|
|
omv_gpio_deinit(spi_pins.miso_pin);
|
|
omv_gpio_deinit(spi_pins.mosi_pin);
|
|
omv_gpio_deinit(spi_pins.ssel_pin);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int alif_hal_pdm_init(uint32_t pdm_id) {
|
|
typedef struct {
|
|
omv_gpio_t clk_pin;
|
|
omv_gpio_t dat_pin;
|
|
} pdm_pins_t;
|
|
|
|
pdm_pins_t pdm_pins = { NULL, NULL };
|
|
|
|
switch (pdm_id) {
|
|
#if defined(OMV_PDM0_ID)
|
|
case OMV_PDM0_ID: {
|
|
enable_pdm_periph_clk();
|
|
pdm_pins = (pdm_pins_t) {
|
|
OMV_PDM0_C0_PIN, OMV_PDM0_D0_PIN
|
|
};
|
|
break;
|
|
}
|
|
#endif
|
|
#if defined(OMV_PDM1_ID)
|
|
case OMV_PDM1_ID: {
|
|
enable_lppdm_periph_clk();
|
|
pdm_pins = (pdm_pins_t) {
|
|
OMV_PDM1_C0_PIN, OMV_PDM1_D0_PIN
|
|
};
|
|
break;
|
|
}
|
|
#endif
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
omv_gpio_config(pdm_pins.clk_pin, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
|
|
omv_gpio_config(pdm_pins.dat_pin, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
|
|
return 0;
|
|
}
|
|
|
|
int alif_hal_pdm_deinit(uint32_t pdm_id) {
|
|
typedef struct {
|
|
omv_gpio_t clk_pin;
|
|
omv_gpio_t dat_pin;
|
|
} pdm_pins_t;
|
|
|
|
pdm_pins_t pdm_pins = { NULL, NULL };
|
|
|
|
switch (pdm_id) {
|
|
#if defined(OMV_PDM0_ID)
|
|
case OMV_PDM0_ID: {
|
|
disable_pdm_periph_clk();
|
|
pdm_pins = (pdm_pins_t) {
|
|
OMV_PDM0_C0_PIN, OMV_PDM0_D0_PIN
|
|
};
|
|
break;
|
|
}
|
|
#endif
|
|
#if defined(OMV_PDM1_ID)
|
|
case OMV_PDM1_ID: {
|
|
disable_lppdm_periph_clk();
|
|
pdm_pins = (pdm_pins_t) {
|
|
OMV_PDM1_C0_PIN, OMV_PDM1_D0_PIN
|
|
};
|
|
break;
|
|
}
|
|
#endif
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
omv_gpio_deinit(pdm_pins.clk_pin);
|
|
omv_gpio_deinit(pdm_pins.dat_pin);
|
|
return 0;
|
|
}
|
|
|
|
int alif_hal_csi_init(CPI_Type *cpi) {
|
|
// Enable CPI clock.
|
|
if (cpi == ((CPI_Type *) CPI_BASE)) {
|
|
enable_cpi_periph_clk();
|
|
} else {
|
|
enable_lpcpi_periph_clk();
|
|
}
|
|
|
|
// Configure CPI pins.
|
|
omv_gpio_config(OMV_CSI_D0_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
|
|
omv_gpio_config(OMV_CSI_D1_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
|
|
omv_gpio_config(OMV_CSI_D2_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
|
|
omv_gpio_config(OMV_CSI_D3_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
|
|
omv_gpio_config(OMV_CSI_D4_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
|
|
omv_gpio_config(OMV_CSI_D5_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
|
|
omv_gpio_config(OMV_CSI_D6_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
|
|
omv_gpio_config(OMV_CSI_D7_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
|
|
|
|
omv_gpio_config(OMV_CSI_HSYNC_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
|
|
omv_gpio_config(OMV_CSI_VSYNC_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
|
|
omv_gpio_config(OMV_CSI_PXCLK_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
|
|
omv_gpio_config(OMV_CSI_MXCLK_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void alif_hal_mpu_init(void) {
|
|
static const ARM_MPU_Region_t MPU_CONFIG_TABLE[] __STARTUP_RO_DATA_ATTRIBUTE = {
|
|
[MPU_REGION_SRAM0] = { /* SRAM0 - 4MB : RO-0, NP-1, XN-0 */
|
|
.RBAR = ARM_MPU_RBAR(0x02000000, ARM_MPU_SH_NON, 0, 1, 0),
|
|
.RLAR = ARM_MPU_RLAR(0x023FFFFF, MPU_ATTR_NORMAL_WT_RA_TRANSIENT)
|
|
},
|
|
[MPU_REGION_SRAM1] = { /* SRAM1 - 2.5MB : RO-0, NP-1, XN-0 */
|
|
.RBAR = ARM_MPU_RBAR(0x08000000, ARM_MPU_SH_NON, 0, 1, 0),
|
|
.RLAR = ARM_MPU_RLAR(0x0827FFFF, MPU_ATTR_NORMAL_WB_RA_WA)
|
|
},
|
|
[MPU_REGION_HOST_PERIPHERALS] = { /* Host Peripherals - 16MB : RO-0, NP-1, XN-1 */
|
|
.RBAR = ARM_MPU_RBAR(0x1A000000, ARM_MPU_SH_NON, 0, 1, 1),
|
|
.RLAR = ARM_MPU_RLAR(0x1AFFFFFF, MPU_ATTR_DEVICE_nGnRE)
|
|
},
|
|
[MPU_REGION_MRAM] = { /* MRAM - 5.5MB : RO-1, NP-1, XN-0 */
|
|
.RBAR = ARM_MPU_RBAR(0x80000000, ARM_MPU_SH_NON, 1, 1, 0),
|
|
.RLAR = ARM_MPU_RLAR(0x8057FFFF, MPU_ATTR_NORMAL_WT_RA)
|
|
},
|
|
[MPU_REGION_OSPI_REGISTERS] = { /* OSPI Regs - 16MB : RO-0, NP-1, XN-1 */
|
|
.RBAR = ARM_MPU_RBAR(0x83000000, ARM_MPU_SH_NON, 0, 1, 1),
|
|
.RLAR = ARM_MPU_RLAR(0x83FFFFFF, MPU_ATTR_DEVICE_nGnRE)
|
|
},
|
|
[MPU_REGION_OSPI0_XIP] = { /* OSPI0 XIP flash - 512MB : RO-1, NP-1, XN-0 */
|
|
.RBAR = ARM_MPU_RBAR(0xA0000000, ARM_MPU_SH_NON, 1, 1, 0),
|
|
.RLAR = ARM_MPU_RLAR(0xBFFFFFFF, MPU_ATTR_NORMAL_NON_CACHEABLE)
|
|
},
|
|
[MPU_REGION_OSPI1_XIP] = { /* OSPI1 XIP flash - 512MB : RO-1, NP-1, XN-0 */
|
|
.RBAR = ARM_MPU_RBAR(0xC0000000, ARM_MPU_SH_NON, 1, 1, 0),
|
|
.RLAR = ARM_MPU_RLAR(0xDFFFFFFF, MPU_ATTR_NORMAL_NON_CACHEABLE)
|
|
},
|
|
};
|
|
|
|
// Disable IRQs.
|
|
uint32_t primask = __get_PRIMASK();
|
|
__disable_irq();
|
|
|
|
// Disable MPU
|
|
ARM_MPU_Disable();
|
|
|
|
// Clear all regions.
|
|
for (size_t i = 0; i < (MPU->TYPE >> 8); i++) {
|
|
ARM_MPU_ClrRegion(i);
|
|
}
|
|
|
|
// Mem Attribute for 0th index
|
|
ARM_MPU_SetMemAttr(MPU_ATTR_NORMAL_WT_RA_TRANSIENT, ARM_MPU_ATTR(
|
|
/* NT=0, WB=0, RA=1, WA=0 */
|
|
ARM_MPU_ATTR_MEMORY_(0, 0, 1, 0),
|
|
ARM_MPU_ATTR_MEMORY_(0, 0, 1, 0)));
|
|
|
|
// Mem Attribute for 1st index
|
|
ARM_MPU_SetMemAttr(MPU_ATTR_DEVICE_nGnRE, ARM_MPU_ATTR(
|
|
/* Device Memory */
|
|
ARM_MPU_ATTR_DEVICE,
|
|
ARM_MPU_ATTR_DEVICE_nGnRE));
|
|
|
|
// Mem Attribute for 2nd index
|
|
ARM_MPU_SetMemAttr(MPU_ATTR_NORMAL_WB_RA_WA, ARM_MPU_ATTR(
|
|
/* NT=1, WB=1, RA=1, WA=1 */
|
|
ARM_MPU_ATTR_MEMORY_(1, 1, 1, 1),
|
|
ARM_MPU_ATTR_MEMORY_(1, 1, 1, 1)));
|
|
|
|
// Mem Attribute for 3th index
|
|
ARM_MPU_SetMemAttr(MPU_ATTR_NORMAL_WT_RA, ARM_MPU_ATTR(
|
|
/* NT=1, WB=0, RA=1, WA=0 */
|
|
ARM_MPU_ATTR_MEMORY_(1, 0, 1, 0),
|
|
ARM_MPU_ATTR_MEMORY_(1, 0, 1, 0)));
|
|
|
|
// Mem Attribute for 4th index
|
|
ARM_MPU_SetMemAttr(MPU_ATTR_NORMAL_NON_CACHEABLE, ARM_MPU_ATTR(
|
|
ARM_MPU_ATTR_NON_CACHEABLE,
|
|
ARM_MPU_ATTR_NON_CACHEABLE));
|
|
|
|
// Load the MPU regions.
|
|
ARM_MPU_Load(0, MPU_CONFIG_TABLE, sizeof(MPU_CONFIG_TABLE) / sizeof(ARM_MPU_Region_t));
|
|
|
|
// Configure MPU regions.
|
|
typedef struct {
|
|
uint32_t addr;
|
|
uint32_t size;
|
|
} dma_memory_table_t;
|
|
|
|
// Start after the last region used by the startup code.
|
|
uint8_t region_number = MPU_REGION_FIRST_FREE;
|
|
extern const dma_memory_table_t _dma_memory_table_start;
|
|
extern const dma_memory_table_t _dma_memory_table_end;
|
|
|
|
for (dma_memory_table_t const *buf = &_dma_memory_table_start; buf < &_dma_memory_table_end; buf++) {
|
|
uint32_t region_base = buf->addr;
|
|
uint32_t region_size = buf->size;
|
|
if (region_size) {
|
|
MPU->RNR = region_number++;
|
|
MPU->RBAR = ARM_MPU_RBAR(region_base, ARM_MPU_SH_NON, 0, 1, 0); // RO-0, NP-1, XN-0
|
|
MPU->RLAR = ARM_MPU_RLAR(region_base + region_size - 1, MPU_ATTR_NORMAL_NON_CACHEABLE);
|
|
}
|
|
}
|
|
|
|
// Re-enable MPU
|
|
ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk);
|
|
|
|
// Re-enable IRQs.
|
|
__set_PRIMASK(primask);
|
|
}
|
|
|
|
// Bypass startup MPU defaults.
|
|
void MPU_Setup(void) {
|
|
|
|
}
|
|
|
|
// Bypass startup MPU defaults.
|
|
void MPU_Load_Regions(void) {
|
|
|
|
}
|
|
|
|
// Used by MicroPython VFS.
|
|
void mpu_config_mram(bool read_only) {
|
|
// Disable IRQs.
|
|
uint32_t primask = __get_PRIMASK();
|
|
__disable_irq();
|
|
|
|
// Disable MPU
|
|
ARM_MPU_Disable();
|
|
|
|
MPU->RNR = MPU_REGION_MRAM;
|
|
MPU->RBAR = ARM_MPU_RBAR(MRAM_BASE, ARM_MPU_SH_NON, read_only, 1, 0);
|
|
MPU->RLAR = ARM_MPU_RLAR(MRAM_BASE + MRAM_SIZE - 1, MPU_ATTR_NORMAL_WT_RA);
|
|
|
|
// Re-enable MPU
|
|
ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk);
|
|
|
|
// Re-enable IRQs.
|
|
__set_PRIMASK(primask);
|
|
}
|