arch/stm32h7: add HSEM support

This commit is contained in:
raiden00pl 2023-08-21 09:40:05 +02:00 committed by Xiang Xiao
parent a967da5270
commit 4c9d405a97
7 changed files with 461 additions and 2 deletions

View File

@ -31,13 +31,16 @@ list(
stm32_rcc.c
stm32_lowputc.c
stm32_serial.c
stm32_uid.c
)
stm32_uid.c)
if(CONFIG_STM32H7_PROGMEM)
list(APPEND SRCS stm32_flash.c)
endif()
if(CONFIG_STM32H7_HSEM)
list(APPEND SRCS stm32_hsem.c)
endif()
if(CONFIG_SCHED_TICKLESS)
list(APPEND SRCS stm32_tickless.c)
else()

View File

@ -633,6 +633,10 @@ config STM32H7_LPTIM
bool
default n
config STM32H7_HSEM
bool "Hardware semaphore"
default n
config STM32H7_RTC
bool "RTC"
default n

View File

@ -29,6 +29,10 @@ ifeq ($(CONFIG_STM32H7_PROGMEM),y)
CHIP_CSRCS += stm32_flash.c
endif
ifeq ($(CONFIG_STM32H7_HSEM),y)
CHIP_CSRCS += stm32_hsem.c
endif
# Required STM32H7 files
CHIP_CSRCS += stm32_allocateheap.c stm32_exti_gpio.c stm32_gpio.c stm32_irq.c

View File

@ -0,0 +1,83 @@
/****************************************************************************
* arch/arm/src/stm32h7/hardware/stm32_hsem.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_ARM_SRC_STM32H7_HARDWARE_STM32_HSEM_H
#define __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32_HSEM_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include "chip.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define STM32_HSEM_CHANS (32)
#define HSEM_COREID_CPU1 (3)
#define HSEM_COREID_CPU2 (1)
/* Register Offsets *********************************************************/
#define STM32_HSEM_RX_OFFSET(n) (0x0000 + (0x4 * n)) /* HSEM register semaphore x */
#define STM32_HSEM_RLRX_OFFSET(n) (0x0080 + (0x4 * n)) /* HSEM read lock register semaphore x */
#define STM32_HSEM_CXIER_OFFSET(n) (0x0100 + (0x10 * n)) /* HSEM interrupt enable register */
#define STM32_HSEM_CXICR_OFFSET(n) (0x0104 + (0x10 * n)) /* HSEM interrupt clear register */
#define STM32_HSEM_CXISR_OFFSET(n) (0x0108 + (0x10 * n)) /* HSEM interrupt status register */
#define STM32_HSEM_CXMISR_OFFSET(n) (0x010c + (0x10 * n)) /* HSEM interrupt status register */
#define STM32_HSEM_CR_OFFSET (0x0140) /* HSEM clear register */
#define STM32_HSEM_KEYR_OFFSET (0x0144) /* HSEM semaphore clear key */
/* Register Addresses *******************************************************/
#define STM32_HSEM_RX(x) (STM32_HSEM_BASE+STM32_HSEM_RX_OFFSET(x))
#define STM32_HSEM_RLRX(x) (STM32_HSEM_BASE+STM32_HSEM_RLRX_OFFSET(x))
#define STM32_HSEM_CXIER(x) (STM32_HSEM_BASE+STM32_HSEM_CXIER_OFFSET(x))
#define STM32_HSEM_CXICR(x) (STM32_HSEM_BASE+STM32_HSEM_CXICR_OFFSET(x))
#define STM32_HSEM_CXISR(x) (STM32_HSEM_BASE+STM32_HSEM_CXISR_OFFSET(x))
#define STM32_HSEM_CXMISR(x) (STM32_HSEM_BASE+STM32_HSEM_CXMISR_OFFSET(x))
#define STM32_HSEM_CXMISRCR (STM32_HSEM_BASE+STM32_HSEM_CR_OFFSET)
#define STM32_HSEM_KEYR (STM32_HSEM_BASE+STM32_HSEM_KEYR_OFFSET)
/* Register Bitfield Definitions ********************************************/
/* Semaphore x registers */
#define HSEM_SEMX_PROCID_SHIFT (0) /* Bits 0-8: Semaphore PROCID */
#define HSEM_SEMX_PROCID_MASK (0xff << HSEM_SEMX_PROCID_SHIFT)
#define HSEM_SEMX_COREID_SHIFT (8) /* Bits 8-11: Semaphore COREID */
#define HSEM_SEMX_COREID_MASK (0xf << HSEM_SEMX_COREID_SHIFT)
/* Bits 12-30: reserved */
#define HSEM_SEMX_LOCK (1 << 31) /* Bit 31: Lock indication */
/* Clear register */
#define HSEM_CR_COREID_SHIFT (8) /* Bits 8-11: COREID of semaphores to be cleared */
#define HSEM_CR_COREID_MASK (0xf << HSEM_CR_COREID_SHIFT)
#define HSEM_CR_KEY_SHIFT (16) /* Bits 16-31: Semaphore clear Key */
#define HSEM_CR_KEY_MASK (0xffff << HSEM_CR_KEY_SHIFT)
/* Interrupts */
#define HSEM_CHAN_ID(n) (1 << n)
#endif /* __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32_HSEM_H */

View File

@ -0,0 +1,291 @@
/****************************************************************************
* arch/arm/src/stm32h7/stm32_hsem.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>
#include <debug.h>
#include "nvic.h"
#include "arm_internal.h"
#include "stm32_hsem.h"
/****************************************************************************
* Private Types
****************************************************************************/
/* HSEM receive channel configuration */
struct stm32_hsem_recv_s
{
hsem_callback_t callback;
void *args;
};
/* HSEM device */
struct stm32_hsem_s
{
struct stm32_hsem_recv_s recv[STM32_HSEM_CHANS];
uint32_t irq;
uint8_t block;
};
/****************************************************************************
* Private Data
****************************************************************************/
struct stm32_hsem_s g_stm32_hsem;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: stm32_hsem_interrupt
****************************************************************************/
static int stm32_hsem_interrupt(int irq, void *context, void *args)
{
struct stm32_hsem_s *dev = args;
uint32_t regval = 0;
int i = 0;
regval = getreg32(STM32_HSEM_CXMISR(dev->block));
_info("HSEM interrupt 0x%" PRIx32 "\n", regval);
for (i = 0; i < STM32_HSEM_CHANS; i++)
{
if (regval & HSEM_CHAN_ID(i))
{
if (dev->recv[i].callback)
{
dev->recv[i].callback(i, dev->recv[i].args);
}
}
}
/* Clear events */
putreg32(regval, STM32_HSEM_CXICR(dev->block));
return 0;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: stm32_hsem_subscribe
*
* Description:
* Subscribe to event on a given semaphore
*
****************************************************************************/
void stm32_hsem_subscribe(uint8_t id, hsem_callback_t callback, void *args)
{
struct stm32_hsem_s *dev = &g_stm32_hsem;
DEBUGASSERT(id < STM32_HSEM_CHANS);
_info("HSEM subscribe %d\n", id);
/* Register callaback */
dev->recv[id].callback = callback;
dev->recv[id].args = args;
if (callback)
{
/* Clear pending */
putreg32(HSEM_CHAN_ID(id), STM32_HSEM_CXICR(dev->block));
/* Enable interrupt */
modifyreg32(STM32_HSEM_CXIER(dev->block), 0, HSEM_CHAN_ID(id));
}
else
{
/* Disable interrupts */
modifyreg32(STM32_HSEM_CXIER(dev->block), HSEM_CHAN_ID(id), 0);
}
}
/****************************************************************************
* Name: stm32_hsem_signal
*
* Description:
* Signal on a semaphore (free and lock again)
*
****************************************************************************/
void stm32_hsem_signal(uint8_t id)
{
DEBUGASSERT(id < STM32_HSEM_CHANS);
_info("HSEM signal %d\n", id);
/* Lock semaphore */
while (stm32_hsem_take(id) == 0);
/* Free semaphore to signal event */
stm32_hsem_free(id);
}
/****************************************************************************
* Name: stm32_hsem_busywait_lock
*
* Description:
* Busy wait for a semaphore to be locked
*
****************************************************************************/
void stm32_hsem_busywait_lock(uint8_t id)
{
DEBUGASSERT(id < STM32_HSEM_CHANS);
_info("HSEM busywait lock %d\n", id);
/* Wait for semaphore lock */
while ((getreg32(STM32_HSEM_RX(id)) & HSEM_SEMX_LOCK) == 0);
}
/****************************************************************************
* Name: stm32_hsem_busywait_free
*
* Description:
* Busy wait for a semaphore to be free
*
****************************************************************************/
void stm32_hsem_busywait_free(uint8_t id)
{
DEBUGASSERT(id < STM32_HSEM_CHANS);
_info("HSEM busywait free %d\n", id);
/* Wait for semaphore free */
while ((getreg32(STM32_HSEM_RX(id)) & HSEM_SEMX_LOCK) != 0);
}
/****************************************************************************
* Name: stm32_hsem_wait_take
*
* Description:
* Take a semaphore (1-step lock)
*
****************************************************************************/
void stm32_hsem_wait_take(uint8_t id)
{
DEBUGASSERT(id < STM32_HSEM_CHANS);
_info("HSEM wait take %d\n", id);
stm32_hsem_busywait_free(id);
while (stm32_hsem_take(id) == 0);
}
/****************************************************************************
* Name: stm32_hsem_take
*
* Description:
* Take a semaphore (1-step lock)
*
****************************************************************************/
bool stm32_hsem_take(uint8_t id)
{
DEBUGASSERT(id < STM32_HSEM_CHANS);
_info("HSEM take %d\n", id);
/* Take semaphore */
#ifdef CONFIG_ARCH_CHIP_STM32H7_CORTEXM7
return (getreg32(STM32_HSEM_RLRX(id)) ==
((HSEM_COREID_CPU1 << HSEM_SEMX_COREID_SHIFT) | HSEM_SEMX_LOCK));
#else
return (getreg32(STM32_HSEM_RLRX(id)) ==
((HSEM_COREID_CPU2 << HSEM_SEMX_COREID_SHIFT) | HSEM_SEMX_LOCK));
#endif
}
/****************************************************************************
* Name: stm32_hsem_free
*
* Description:
* Free a semaphore
*
****************************************************************************/
void stm32_hsem_free(uint8_t id)
{
#ifdef CONFIG_ARCH_CHIP_STM32H7_CORTEXM7
putreg32((HSEM_COREID_CPU1 << HSEM_CR_COREID_SHIFT) , STM32_HSEM_RX(id));
#else
putreg32((HSEM_COREID_CPU2 << HSEM_CR_COREID_SHIFT) , STM32_HSEM_RX(id));
#endif
}
/****************************************************************************
* Name: stm32_hsem_init
*
* Description:
* Initialize the hardware semaphore driver
*
****************************************************************************/
void stm32_hsem_init(void)
{
struct stm32_hsem_s *dev = &g_stm32_hsem;
/* Reset device */
memset(dev, 0, sizeof(struct stm32_hsem_s));
/* Set block id */
#ifdef CONFIG_ARCH_CHIP_STM32H7_CORTEXM7
dev->block = 0;
dev->irq = STM32_IRQ_HSEM0;
#else
dev->block = 1;
dev->irq = STM32_IRQ_HSEM1;
#endif
/* Attach and enable the IRQ */
irq_attach(dev->irq, stm32_hsem_interrupt, dev);
up_enable_irq(dev->irq);
}

View File

@ -0,0 +1,68 @@
/****************************************************************************
* arch/arm/src/stm32h7/stm32_hsem.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_ARM_SRC_STM32H7_STM32_HSEM_H
#define __ARCH_ARM_SRC_STM32H7_STM32_HSEM_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include "hardware/stm32_hsem.h"
/****************************************************************************
* Public Types
****************************************************************************/
typedef void (*hsem_callback_t)(uint8_t id, void *arg);
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifndef __ASSEMBLY__
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
void stm32_hsem_subscribe(uint8_t id, hsem_callback_t callback, void *args);
void stm32_hsem_signal(uint8_t id);
void stm32_hsem_busywait_lock(uint8_t id);
void stm32_hsem_busywait_free(uint8_t id);
void stm32_hsem_wait_take(uint8_t id);
bool stm32_hsem_take(uint8_t id);
void stm32_hsem_free(uint8_t id);
void stm32_hsem_init(void);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_ARM_SRC_STM32H7_STM32_HSEM_H */

View File

@ -416,6 +416,12 @@ static inline void rcc_enableahb4(void)
regval |= RCC_AHB4ENR_BKPSRAMEN;
#endif
#ifdef CONFIG_STM32H7_HSEM
/* HSEM clock enable */
regval |= RCC_AHB4ENR_HSEMEN;
#endif
putreg32(regval, STM32_RCC_AHB4ENR); /* Enable peripherals */
}