diff --git a/arch/arm64/src/common/Make.defs b/arch/arm64/src/common/Make.defs index 9576ed59bb..4bb12ec7eb 100644 --- a/arch/arm64/src/common/Make.defs +++ b/arch/arm64/src/common/Make.defs @@ -54,6 +54,7 @@ CMN_CSRCS += arm64_perf.c arm64_tcbinfo.c CMN_CSRCS += arm64_arch_timer.c arm64_cache.c CMN_CSRCS += arm64_doirq.c arm64_fatal.c CMN_CSRCS += arm64_syscall.c +CMN_CSRCS += arm64_modifyreg8.c arm64_modifyreg16.c arm64_modifyreg32.c # Use common heap allocation for now (may need to be customized later) CMN_CSRCS += arm64_allocateheap.c diff --git a/arch/arm64/src/common/arm64_arch.h b/arch/arm64/src/common/arm64_arch.h index a73a76e2f4..de47814d9d 100644 --- a/arch/arm64/src/common/arm64_arch.h +++ b/arch/arm64/src/common/arm64_arch.h @@ -478,10 +478,18 @@ static inline void arch_nop(void) ::: "memory"); \ }) +/* Non-atomic modification of registers */ + #define modreg8(v,m,a) putreg8((getreg8(a) & ~(m)) | ((v) & (m)), (a)) #define modreg16(v,m,a) putreg16((getreg16(a) & ~(m)) | ((v) & (m)), (a)) #define modreg32(v,m,a) putreg32((getreg32(a) & ~(m)) | ((v) & (m)), (a)) +/* Atomic modification of registers */ + +void modifyreg8(unsigned int addr, uint8_t clearbits, uint8_t setbits); +void modifyreg16(unsigned int addr, uint16_t clearbits, uint16_t setbits); +void modifyreg32(unsigned int addr, uint32_t clearbits, uint32_t setbits); + /**************************************************************************** * Name: * arch_get_exception_depth diff --git a/arch/arm64/src/common/arm64_modifyreg16.c b/arch/arm64/src/common/arm64_modifyreg16.c new file mode 100644 index 0000000000..3c1fd2e498 --- /dev/null +++ b/arch/arm64/src/common/arm64_modifyreg16.c @@ -0,0 +1,57 @@ +/**************************************************************************** + * arch/arm64/src/common/arm64_modifyreg16.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 + +#include +#include + +#include + +#include "arm64_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: modifyreg16 + * + * Description: + * Atomically modify the specified bits in a memory mapped register + * + ****************************************************************************/ + +void modifyreg16(unsigned int addr, uint16_t clearbits, uint16_t setbits) +{ + irqstate_t flags; + uint16_t regval; + + flags = spin_lock_irqsave(NULL); + regval = getreg16(addr); + regval &= ~clearbits; + regval |= setbits; + putreg16(regval, addr); + spin_unlock_irqrestore(NULL, flags); +} diff --git a/arch/arm64/src/common/arm64_modifyreg32.c b/arch/arm64/src/common/arm64_modifyreg32.c new file mode 100644 index 0000000000..c3fc742739 --- /dev/null +++ b/arch/arm64/src/common/arm64_modifyreg32.c @@ -0,0 +1,57 @@ +/**************************************************************************** + * arch/arm64/src/common/arm64_modifyreg32.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 + +#include +#include + +#include + +#include "arm64_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: modifyreg32 + * + * Description: + * Atomically modify the specified bits in a memory mapped register + * + ****************************************************************************/ + +void modifyreg32(unsigned int addr, uint32_t clearbits, uint32_t setbits) +{ + irqstate_t flags; + uint32_t regval; + + flags = spin_lock_irqsave(NULL); + regval = getreg32(addr); + regval &= ~clearbits; + regval |= setbits; + putreg32(regval, addr); + spin_unlock_irqrestore(NULL, flags); +} diff --git a/arch/arm64/src/common/arm64_modifyreg8.c b/arch/arm64/src/common/arm64_modifyreg8.c new file mode 100644 index 0000000000..cb230b257e --- /dev/null +++ b/arch/arm64/src/common/arm64_modifyreg8.c @@ -0,0 +1,57 @@ +/**************************************************************************** + * arch/arm64/src/common/arm64_modifyreg8.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 + +#include +#include + +#include + +#include "arm64_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: modifyreg8 + * + * Description: + * Atomically modify the specified bits in a memory mapped register + * + ****************************************************************************/ + +void modifyreg8(unsigned int addr, uint8_t clearbits, uint8_t setbits) +{ + irqstate_t flags; + uint8_t regval; + + flags = spin_lock_irqsave(NULL); + regval = getreg8(addr); + regval &= ~clearbits; + regval |= setbits; + putreg8(regval, addr); + spin_unlock_irqrestore(NULL, flags); +}