mirror of
https://github.com/RfidResearchGroup/ChameleonMini.git
synced 2026-05-12 11:20:37 -07:00
While in the process of writing a new codec I stumbled upon the long standing issue of ISR sharing in AVR MCUs. Actually this is accomplished with an ISR written in C, which simply calls another plain C function referenced via a function pointer updated at runtime. This approach is slow because GCC can't optimize the ISR, since it does not know which registers will be used, so it defaults to push/pop all of them. My solution keeps the concept of pointers to functions, but greatly improves speed by reducing the ISR itself to the bare minimum to call another function, which will be compiled by GCC as a signal. This means all interrupt optimizations will be put in place by GCC, while ISRs can be still written in plain C code, but the overhead is now much smaller. It has proven to reduce by 20 the number of instructions for every ISR, mainly pushes/pops, which cuts the clock cycle count down by 30 cycles (1 cycle for every push, 2 for pop). In time units, this means 1.1 uSec are saved for every ISR invocation and every shared ISR now takes only 13 clock cycles more than the "bare" one. A new ISR_SHARED function type has been defined in Common.h to hide away from the programmer GCC attributes. All new shared interrupt handling routines should be defined of this type to prevent stack and registers corruption. Minor changes were made to Codec.h to allow including it in .S files.
69 lines
1.8 KiB
C
69 lines
1.8 KiB
C
/*
|
|
* Common.h
|
|
*
|
|
* Created on: 20.03.2013
|
|
* Author: skuser
|
|
*/
|
|
|
|
#ifndef COMMON_H_
|
|
#define COMMON_H_
|
|
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include <util/parity.h>
|
|
#include <util/delay.h>
|
|
#include <avr/pgmspace.h>
|
|
#include <avr/io.h>
|
|
|
|
#define ODD_PARITY(Value) OddParityBit(Value)//(parity_even_bit(Value) ? 0 : 1)
|
|
|
|
#define ISR_SHARED \
|
|
void __attribute__((signal)) // This function type has to be used for all the interrupt handlers that have to be changed at runtime
|
|
|
|
#define INLINE \
|
|
static inline __attribute__((always_inline))
|
|
|
|
#define ARRAY_COUNT(x) \
|
|
(sizeof(x) / sizeof(x[0]))
|
|
|
|
#define NIBBLE_TO_HEXCHAR(x) ( (x) < 0x0A ? (x) + '0' : (x) + 'A' - 0x0A )
|
|
#define HEXCHAR_TO_NIBBLE(x) ( (x) < 'A' ? (x) - '0' : (x) - 'A' + 0x0A )
|
|
#define VALID_HEXCHAR(x) ( ( (x) >= '0' && (x) <= '9' ) || ( (x) >= 'A' && (x) <= 'F' ) )
|
|
#define MIN(x,y) ( (x) < (y) ? (x) : (y) )
|
|
#define MAX(x,y) ( (x) > (y) ? (x) : (y) )
|
|
#define SYSTICK_DIFF(since) ((uint16_t) (SystemGetSysTick() - since))
|
|
#define SYSTICK_DIFF_100MS(since) (SYSTICK_DIFF(since) / 100)
|
|
|
|
#define BITS_PER_BYTE 8
|
|
|
|
uint16_t BufferToHexString(char *HexOut, uint16_t MaxChars, const void *Buffer, uint16_t ByteCount);
|
|
uint16_t HexStringToBuffer(void *Buffer, uint16_t MaxBytes, const char *HexIn);
|
|
|
|
INLINE uint8_t BitReverseByte(uint8_t Byte) {
|
|
extern const uint8_t PROGMEM BitReverseByteTable[];
|
|
|
|
return pgm_read_byte(&BitReverseByteTable[Byte]);
|
|
}
|
|
|
|
INLINE uint8_t OddParityBit(uint8_t Byte) {
|
|
extern const uint8_t PROGMEM OddParityByteTable[];
|
|
|
|
return pgm_read_byte(&OddParityByteTable[Byte]);
|
|
}
|
|
|
|
INLINE uint8_t StringLength(const char *Str, uint8_t MaxLen) {
|
|
uint8_t StrLen = 0;
|
|
|
|
while (MaxLen > 0) {
|
|
if (*Str++ == '\0')
|
|
break;
|
|
|
|
MaxLen--;
|
|
StrLen++;
|
|
}
|
|
|
|
return StrLen;
|
|
}
|
|
|
|
#endif /* COMMON_H_ */
|