compare_set.h 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #pragma once
  7. #include <stdint.h>
  8. #include <stdbool.h>
  9. #include "soc/cpu.h"
  10. #include "soc/soc_memory_types.h"
  11. #if __XTENSA__
  12. #include "xtensa/xtruntime.h"
  13. #endif
  14. #ifdef __cplusplus
  15. extern "C" {
  16. #endif
  17. static inline void __attribute__((always_inline)) compare_and_set_native(volatile uint32_t *addr, uint32_t compare, uint32_t *set)
  18. {
  19. #if (XCHAL_HAVE_S32C1I > 0)
  20. __asm__ __volatile__ (
  21. "WSR %2,SCOMPARE1 \n"
  22. "S32C1I %0, %1, 0 \n"
  23. :"=r"(*set)
  24. :"r"(addr), "r"(compare), "0"(*set)
  25. );
  26. #else
  27. uint32_t old_value;
  28. #ifdef __XTENSA__
  29. // No S32C1I, so do this by disabling and re-enabling interrupts (slower)
  30. uint32_t intlevel;
  31. __asm__ __volatile__ ("rsil %0, " XTSTR(XCHAL_EXCM_LEVEL) "\n"
  32. : "=r"(intlevel));
  33. #else
  34. unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
  35. #endif
  36. old_value = *addr;
  37. if (old_value == compare) {
  38. *addr = *set;
  39. }
  40. #ifdef __XTENSA__
  41. __asm__ __volatile__ ("memw \n"
  42. "wsr %0, ps\n"
  43. :: "r"(intlevel));
  44. #else
  45. RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
  46. #endif
  47. *set = old_value;
  48. #endif
  49. }
  50. void compare_and_set_extram(volatile uint32_t *addr, uint32_t compare, uint32_t *set);
  51. #ifdef __cplusplus
  52. }
  53. #endif