compare_set.h 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. // Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #pragma once
  15. #include <stdint.h>
  16. #include <stdbool.h>
  17. #include "soc/cpu.h"
  18. #include "soc/soc_memory_layout.h"
  19. #if __XTENSA__
  20. #include "xtensa/xtruntime.h"
  21. #endif
  22. #ifdef __cplusplus
  23. extern "C" {
  24. #endif
  25. static inline void __attribute__((always_inline)) compare_and_set_native(volatile uint32_t *addr, uint32_t compare, uint32_t *set)
  26. {
  27. #if (XCHAL_HAVE_S32C1I > 0)
  28. __asm__ __volatile__ (
  29. "WSR %2,SCOMPARE1 \n"
  30. "S32C1I %0, %1, 0 \n"
  31. :"=r"(*set)
  32. :"r"(addr), "r"(compare), "0"(*set)
  33. );
  34. #else
  35. uint32_t old_value;
  36. #ifdef __XTENSA__
  37. // No S32C1I, so do this by disabling and re-enabling interrupts (slower)
  38. uint32_t intlevel;
  39. __asm__ __volatile__ ("rsil %0, " XTSTR(XCHAL_EXCM_LEVEL) "\n"
  40. : "=r"(intlevel));
  41. #else
  42. unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
  43. #endif
  44. old_value = *addr;
  45. if (old_value == compare) {
  46. *addr = *set;
  47. }
  48. #ifdef __XTENSA__
  49. __asm__ __volatile__ ("memw \n"
  50. "wsr %0, ps\n"
  51. :: "r"(intlevel));
  52. #else
  53. RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
  54. #endif
  55. *set = old_value;
  56. #endif
  57. }
  58. void compare_and_set_extram(volatile uint32_t *addr, uint32_t compare, uint32_t *set);
  59. #ifdef __cplusplus
  60. }
  61. #endif