Post Go back to editing

Is there a Test and Set Byte (Atomic) in the ARM and SHARC cores?

I'm using an ADSP-SC573. I would like to be able to test and set a byte atomic from the other cores.This byte is located in L2 RAM so it can be shared by all cores. Is thera a way to do it in ARM and SHARC cores?

I think the Blackfin had a testset function but I can't find any for the ARM and SHARC.

I found how to accuire a lock in the SHARC DSP at least:

void acquireLock(volatile uint8_t *lock)
{
 while (true)
 {
   int err;
   int locked = load_exclusive_8((unsigned volatile char *)lock, &err);
   if (err != 0) continue;
   if (locked == 0)
   {
     err = store_exclusive_8(1, (unsigned volatile char *)lock);
     if (err == 0) break;
   }
 }
}

void releaseLock(volatile uint8_t *lock)
{
  while (true)
  {
    int err;
    int locked = load_exclusive_8((unsigned volatile char *)lock, &err);
    if (err != 0) continue;
    if (locked == 1)
    {
      err = store_exclusive_8(0, (unsigned volatile char *)lock);
      if (err == 0) break;
    }
  }
}

For the ARM core I would need to write C/assembly that uses the LDREXB and STREXB instructions. Any tips on how to do that?

NOte: Later I found some code for LDREXB and STREXB at https://github.com/ARM-software/CMSIS/blob/master/CMSIS/Include/cmsis_gcc.h that I tried on the ARM:

/**
  \brief   LDR Exclusive (8 bit)
  \details Executes a exclusive LDR instruction for 8 bit value.
  \param [in]    ptr  Pointer to data
  \return             value of type uint8_t at (*ptr)
 */
uint8_t __LDREXB(volatile uint8_t *addr)
{
   uint32_t result;
   asm  volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) );
   return (uint8_t) result;
}

/**
  \brief   STR Exclusive (8 bit)
  \details Executes a exclusive STR instruction for 8 bit values.
  \param [in]  value  Value to store
  \param [in]    ptr  Pointer to location
  \return          0  Function succeeded
  \return          1  Function failed
 */
uint8_t __STREXB(uint8_t value, volatile uint8_t *addr)
{
   uint32_t result;
   asm  volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
   return (uint8_t)result;
}


void acquireLock(volatile uint8_t *lock)
{
 while (true)
 {
   uint8_t locked = __LDREXB(lock);
   if (locked == 0)
   {
     uint8_t err = __STREXB(1, lock);
     if (err == 0) break;
   }
 }
}

void releaseLock(volatile uint8_t *lock)
{
  while (true)
  {
    uint8_t locked = __LDREXB(lock);
    if (locked == 1)
    {
      uint8_t err = __STREXB(0, lock);
      if (err == 0) break;
    }
  }
}



Added code for ARM
[edited by: masip at 2:01 PM (GMT -4) on 24 Oct 2022]