Thursday, July 27, 2017

Race condition in multithreading: Why to use lock mechanism for shared memory ?

Race condition is race between the users to access some resource.

Example: 
Two thread with no synchronisation or no locking mechanism for variable access, can end up in race condition.

thread1:

if (x == 5) {
    y = x * 2;
}

thread2:
x = 6;

Here problem occurs when check condition in thread1 is done, and then thread2 occurs which chnage x, then the result in y can be different(12) than expected(10).

To solve this kind of problem, Memory lock mechanism, Thread synchronisation, Interprocess ommunication etc. concepts are used.

Volatile and Constant usage

volatile uint32_t x;  // tells compiler not to optimize this. stored on SRAM in global section
const uint32_t x;  // stored on ROM. Part of code memory. Value cant be changed.
volatile const uint32_t x;  // Value cant be changed from the code inside the file where it is declared but can be changed from outside the file.

volatile uint32_t * TCNT;
// TCNT is a pointer to register whose value can be changed outside the scope of program flow.
Read write register. Pointer value (i.e. address of register) can be changed.

const uint32_t * TCNT;
// TCNT is pointer to register whose value cant be changed using pointer dereferencing.
Readonly register. Pointer value (i.e. address of register) can be changed.

volatile uint32_t * const TCNT;
// TCNT is a pointer whose value cant be changed. It point to register whose value can get changed out of flow of program.
Read or Write register.  Pointer value (i.e. address of register) cannot be changed.

const uint32_t * volatile TCNT;
// TCNT is a pointer whose value can be get changed out of flow of code execution. It points to register whose value cant be changed through the code. Its constant and cant be changed by pointer deferencing.
Read only memory.

volatile const uint32_t * const TCNT;
// TCNT is a pointer whose value is constant. It points to register whose value is constant for code, but can get changed out of flow of program execution.
Read only register accessing.

Using pointers, when accessing
- Read only register, whose value is not going to be changed at all use
const uint32_t * ptr;
- Read only register, whose value can change outside the flow of execution
volatile const uint32_t * ptr
- Write register
uint32_t *ptr


Wednesday, July 26, 2017

Clarification on various terms of Embedded microcontrollers

Memory access Architectures:


  • Von-neumann:

Code and data memory on same memory address map
Only one set of address and data bus shared for code, data memory

  • Harvard

Code and data memory on separate memory address map
Two set of address and data bus, one for each memory
eg. 8051, PIC

  • Modified Harvard

1. Almost harvard

Code and data memory on separate memory address map.
But, instruction can be stored on data memory (like SRAM), or data can be stored on Code memory (like FLASH). For accessing data from code memory special instructions are provided.
eg. AVR8

2. Almost von-neumann

Code and data memory on same memory address map
But internal to CPU architecture there are separate instruction and data cache.
Depending on the coherency between the data and instruction cache there are two types:
     a. With coherence (eg. x86, x64)
     b. Without coherence (eg. ARM)
NOTE: Here in ARM architecture, there are possibility of problems with coherency. In order to avoid this the variables should be defined volatile as far as possible. This makes sure, after every operation the output is stored back to SRAM rather than just keeping it on cache and using it for next operation.

Interesting article for the explanation:
http://ithare.com/modified-harvard-architecture-clarifying-confusion/

CPU architecture:


  • 8051

8051is a harvard architecture. Good for small applications, but for big applications where data processing size requried is more. Number of vectored interrupts are less. Lack of memory management unit on chip.

  • PIC

Good for applications where lot of peripheral support required on silicon. It has very small stack memory.

  • AVR

Modified Harvard architecture for 8bit data processing. Good for small applications

  • ARM

Most advanced architecture with memory management, nest vectorred interrupt controller, debug and trace units with support for SWD and JTAG. Capable of operating at high frequencies.

Instruction sets:

  1. CISC - complex instruction set machine

Code size less
Pipelining cant be implemented
Time per instruction not the same.

  1. RISC - reduced instruction set machine

Code size more
Pipelining can be implemented
Time per instruction the same.
Instruction execution statictics are measured in DIPS(Dhrystone instructions per second) or MIPS (milion instruction per second)

Friday, July 21, 2017

Practical significance of Bitfield, union and Structure

/**
  \brief  Union type to access the Special-Purpose Program Status Registers (xPSR).
 */
typedef union
{
  struct
  {
    uint32_t ISR:9;                      /*!< bit:  0.. 8  Exception number */
    uint32_t _reserved0:7;               /*!< bit:  9..15  Reserved */
    uint32_t GE:4;                       /*!< bit: 16..19  Greater than or Equal flags */
    uint32_t _reserved1:4;               /*!< bit: 20..23  Reserved */
    uint32_t T:1;                        /*!< bit:     24  Thumb bit        (read 0) */
    uint32_t IT:2;                       /*!< bit: 25..26  saved IT state   (read 0) */
    uint32_t Q:1;                        /*!< bit:     27  Saturation condition flag */
    uint32_t V:1;                        /*!< bit:     28  Overflow condition code flag */
    uint32_t C:1;                        /*!< bit:     29  Carry condition code flag */
    uint32_t Z:1;                        /*!< bit:     30  Zero condition code flag */
    uint32_t N:1;                        /*!< bit:     31  Negative condition code flag */
  } b;                                   /*!< Structure used for bit  access */
  uint32_t w;                            /*!< Type      used for word access */
} xPSR_Type;

xPSR_Ttpe APSR;

uint32_t var1 = APSR.w;  // If we want to access as a word. Underneath Load Store Instruction
uint8_t var2 = APSR.b.IT;  //If we want to read from bit 25 and 26 only. Under neath Bitfiled instruction.

Hence union brings the freedom of access to a particular register. 

PROFILE

My photo
India
Design Engineer ( IFM Engineering Private Limited )

Followers