Can any one explain what each value in ranges property represent.
my_pcie_0: pcie#10000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "mypcie";
device_type = "pcie";
reg = < 0x40000000 0x00100000 >;
ranges = < 0x02000000 0 0xf0000000 0xf00000000 0x0 0x08000000>;
}
This question has been up for a while but I ran into the same issue and found the answer after searching for a while.
my_pcie_0: pcie#10000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "mypcie";
device_type = "pcie";
reg = < 0x40000000 0x00100000 >;
ranges = < 0x02000000 0 0xf0000000 0xf00000000 0x0 0x08000000>;
}
In the ranges field the first three values specify the address on the PCI bus to be mapped in.
0x02000000 0 0xf0000000
However the device tree treats PCI address translations as a special case where the first value is a bitfield instead of an address. In this case "0x02000000" would specify a non-prefetchable 32-bit memory space.
This leaves "0 0xf0000000" as the high and low parts of the 64-bit PCI address to be mapped in, since the high part is 0, the actual address is 0xf00000000.
The fourth value specifies the address on the CPU's bus to map the segment of the PCI bus into. It is 32-bits on a 32-bit processor.
0xf00000000
The fifth and six values specify the size of the segment to map in. In this case a 128MB segment.
0x0 0x08000000
Knowing this it appears that your cell sizes are incorrect, They should instead be 3 for the address cells to cover a 64-bit PCI address value plus the 32-bit bitfield and 2 for the 64-bit size value. The 32-bit size of the CPU address is inherited from the parent.
#address-cells = <3>;
#size-cells = <2>;
Here's a more in-depth explanation on PCI address translation
This is from the documentation:
ranges = <0 0 0x10100000 0x10000 // Chipselect 1, Ethernet
1 0 0x10160000 0x10000 // Chipselect 2, i2c controller
2 0 0x30000000 0x1000000>; // Chipselect 3, NOR Flash
Related
I need to filter priority into VLAN header to ensure Voice priority value.
Using BPF filtering is possible to evaluate which packets contains priority bits value into VLAN header are equals to five ?
Regards
Vincenzo
Yes you can, the exact way to do it depends on the type of eBPF program.
For programs with __sk_buff contexts(TC, Socket filter, cGroup SKB)
eBPF program types which get a __sk_buff as context can just access the vlan_tci field. This fields should already be in host byte order so you can just mask and bit shift the value to get the PCP field.
For XDP programs
In XDP programs we need to manually parse all network layers before we can access the TCI field.
XDP tutorial has a few parsing functions which are a good base, including parse_ethhdr_vlan:
/* Notice, parse_ethhdr() will skip VLAN tags, by advancing nh->pos and returns
* next header EtherType, BUT the ethhdr pointer supplied still points to the
* Ethernet header. Thus, caller can look at eth->h_proto to see if this was a
* VLAN tagged packet.
*/
static __always_inline int parse_ethhdr_vlan(struct hdr_cursor *nh,
void *data_end,
struct ethhdr **ethhdr,
struct collect_vlans *vlans)
{
struct ethhdr *eth = nh->pos;
int hdrsize = sizeof(*eth);
struct vlan_hdr *vlh;
__u16 h_proto;
int i;
/* Byte-count bounds check; check if current pointer + size of header
* is after data_end.
*/
if (nh->pos + hdrsize > data_end)
return -1;
nh->pos += hdrsize;
*ethhdr = eth;
vlh = nh->pos;
h_proto = eth->h_proto;
/* Use loop unrolling to avoid the verifier restriction on loops;
* support up to VLAN_MAX_DEPTH layers of VLAN encapsulation.
*/
#pragma unroll
for (i = 0; i < VLAN_MAX_DEPTH; i++) {
if (!proto_is_vlan(h_proto))
break;
if (vlh + 1 > data_end)
break;
h_proto = vlh->h_vlan_encapsulated_proto;
if (vlans) /* collect VLAN ids */
vlans->id[i] =
(bpf_ntohs(vlh->h_vlan_TCI) & VLAN_VID_MASK);
vlh++;
}
nh->pos = vlh;
return h_proto; /* network-byte-order */
}
You will have to modify this function for your purposes since it currently discards the PCP field you are after vlans->id[i] = (bpf_ntohs(vlh->h_vlan_TCI) & VLAN_VID_MASK);
I am trying to write a constraint for a data packet in system verilog. I have a data packet whose size can be 0-4096 bits and I need to write a constraint in my packet class in a way that packet should be 4 byte aligned and it should not cross 4k boundary or if the start address is above 4k, it should not cross 8k boundary, and so on upto 1GB. So, the issue is that I can write a constraint for the first 4k boundary as below (if it looks fine ?) but this won't be true if the start address is above 4K and in that case it should not cross 8K or if start address is above 8K, so on, how can I write a generic constraint for the same ??
class packet
int size;
rand bit [31:0] addr; // start address
rand bit [7:0] data[]; // data
rand bit [15:0] size; // size of packet
constraint size_c { size inside [0:4096]; }
constraint addr_c { addr[0:1]==0; // for 4 byte alignment
addr[12:0] <'h1000 - size; }
endclass
I think you're almost there. I think you meant:
addr[11:0] + size <= 32'h1000 ;
I would recommend not using unsized literals, ie I would recommend saying 32'h1000 not 'h1000. This is because the behaviour of such literals changed between Verilog-1995 and Verilog-2001, so it's probably best to just avoid them.
module M;
class packet;
rand bit [13:0] addr; // start address
rand bit [15:0] size; // size of packet
constraint size_c { size inside {[1:4096]}; }
constraint addr_c { addr[1:0]==0; // for 4 byte alignment
addr[11:0] + size <= 32'h1000; }
endclass
initial
begin
packet p = new;
repeat (10)
begin
p.randomize;
$display("%p - %d", p, p.addr[11:0] + p.size);
end
end
endmodule
https://www.edaplayground.com/x/3gtq
From what I understand, the range of QModbusDataUnit::InputRegisters is range 0-65535 which is unsigned short.
The method to read 1 unit of inputregisters is as follows:
QModbusDataUnit readUnit(QModbusDataUnit::InputRegisters, 40006, 1);
The value of that will be in the reply, i.e : int value = result.value(0);
My question is that what if I have to read a value of unsigned int which is much larger of the range of 0 to 4,294,967,295.
How can I retrieve that value?
As you stated, Modbus input registers are 16 bit unsigned integers. So without some type of conversion they are limited to the range: 0 - 65535. For 32-bit unsigned values it is typical (in Modbus) to combine two registers.
For example, the high 16-bits could be stored at 40006 and the low 16-bits at 40007.
So, if you were reading the value 2271560481 (0x87654321 hex), you would read 34661 (0x8765) from address 40006 and 17185 (0x4321 hex) from location 40007. You would then combine them to give you the actual value.
I don't know the Qt Modbus code, but expanding on your example code you can probably read both values at the same time by doing something like this:
readUnit(QModbusDataUnit::InputRegisters, 40006, 2);
and combine them
quint32 value = result.value(0);
value = (value << 16) | result.value(1);
I am currently using the STM32F4 with the STM32F429ZI Nucleo-144 Board. I am looking to use this microcontroller to evaluate the position of a rotary encoder via a quadrature encoder interface. Looking at the documentation, this is done with the timers. I have the A/B encoder outputs hooked up to PA6 and PC7 on the micro, but I have noticed that the counts appear to be drifting.
During the debugging, I noticed that if I disconnect one of the encoder outputs to the microcontroller and I move the motor, the counts still increment/decrement even though only one of the encoder lines are connected. Since I am counting on both the TI1 and TI2 edges, this should not be happening. If I am reading the below diagram correctly, since one of my lines is held high using the internal pull-up, clock pulses on the other input should be going up/down/up/down and really just cycling between two different counts. However, if I am rotating the encoder, the counts keep incrementing or decrementing depending on the direction.
Why is the encoder count changing with only one encoder input connected? I also have the scope trace attached to prove that only one count is is active, as well as the code.
EDIT: I have also tried changing the polarity from BOTH EDGE to RISING EDGE, with no perceived benefit.
#include "stm32f4xx_hal.h"
#include "encoder_test.h"
GPIO_InitTypeDef GPIO_InitStruct;
TIM_HandleTypeDef Timer_InitStruct;
TIM_Encoder_InitTypeDef Encoder_InitStruct;
void EncoderTest_Init()
{
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_TIM3_CLK_ENABLE();
/**TIM3 GPIO Configuration
PA6 ------> TIM3_CH1
PC7 ------> TIM3_CH2
*/
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
Timer_InitStruct.Instance = TIM3;
Timer_InitStruct.Init.Period = 0xFFFF;
Timer_InitStruct.Init.CounterMode = TIM_COUNTERMODE_UP;
Timer_InitStruct.Init.Prescaler = 1;
Timer_InitStruct.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
Encoder_InitStruct.EncoderMode = TIM_ENCODERMODE_TI12;
Encoder_InitStruct.IC1Filter = 0x00;
Encoder_InitStruct.IC1Polarity = TIM_INPUTCHANNELPOLARITY_BOTHEDGE;
Encoder_InitStruct.IC1Prescaler = TIM_ICPSC_DIV1;
Encoder_InitStruct.IC1Selection = TIM_ICSELECTION_DIRECTTI;
Encoder_InitStruct.IC2Filter = 0x00;
Encoder_InitStruct.IC2Polarity = TIM_INPUTCHANNELPOLARITY_BOTHEDGE;
Encoder_InitStruct.IC2Prescaler = TIM_ICPSC_DIV1;
Encoder_InitStruct.IC2Selection = TIM_ICSELECTION_DIRECTTI;
if (HAL_TIM_Encoder_Init(&Timer_InitStruct, &Encoder_InitStruct) != HAL_OK)
{
while (1);
}
if (HAL_TIM_Encoder_Start_IT(&Timer_InitStruct, TIM_CHANNEL_1) != HAL_OK)
{
while (1);
}
}
void TIM3_IRQHandler()
{
HAL_TIM_IRQHandler(&Timer_InitStruct);
}
Upon further investigation, it appears that the issue is due to the prescaler. The prescaler does not work in encoder mode when you provide even values. Since prescaler is the entered value + 1, using the STM32F4 HAL, the entered prescaler must be even.
I found confirmation that I am not the only person with this issue at this forum post. There is some discussion at the post that prescalers may not be compatible with encoder mode, but this has not yet been confirmed. I have sent an email to ST to get to the bottom of it. It is safe to enter a prescaler value of 0 if it is not supported.
Here is the working code below:
#include "stm32f4xx_hal.h"
#include "encoder_test.h"
GPIO_InitTypeDef GPIO_InitStruct;
TIM_HandleTypeDef Timer3_InitStruct;
TIM_Encoder_InitTypeDef EncoderTim3_InitStruct;
void EncoderTest_Init_Tim3()
{
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_TIM3_CLK_ENABLE();
/**TIM3 GPIO Configuration
PA6 ------> TIM3_CH1
PC7 ------> TIM3_CH2
*/
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
Timer3_InitStruct.Instance = TIM3;
Timer3_InitStruct.Init.Period = 0xFFFF;
Timer3_InitStruct.Init.CounterMode = TIM_COUNTERMODE_UP;
Timer3_InitStruct.Init.Prescaler = 10;
Timer3_InitStruct.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
EncoderTim3_InitStruct.EncoderMode = TIM_ENCODERMODE_TI12;
EncoderTim3_InitStruct.IC1Filter = 0x00;
EncoderTim3_InitStruct.IC1Polarity = TIM_INPUTCHANNELPOLARITY_RISING;
EncoderTim3_InitStruct.IC1Prescaler = TIM_ICPSC_DIV4;
EncoderTim3_InitStruct.IC1Selection = TIM_ICSELECTION_DIRECTTI;
EncoderTim3_InitStruct.IC2Filter = 0x00;
EncoderTim3_InitStruct.IC2Polarity = TIM_INPUTCHANNELPOLARITY_RISING;
EncoderTim3_InitStruct.IC2Prescaler = TIM_ICPSC_DIV4;
EncoderTim3_InitStruct.IC2Selection = TIM_ICSELECTION_DIRECTTI;
if (HAL_TIM_Encoder_Init(&Timer3_InitStruct, &EncoderTim3_InitStruct) != HAL_OK)
{
while (1);
}
if (HAL_TIM_Encoder_Start_IT(&Timer3_InitStruct, TIM_CHANNEL_1) != HAL_OK)
{
while (1);
}
}
void TIM3_IRQHandler()
{
HAL_TIM_IRQHandler(&Timer3_InitStruct);
}
EDIT:
After speaking with ST tech support, the encoder interface was not intended to be used with a prescaler value, even OR odd. I have pasted their response below, but even with using a prescaler value that appears to work, it seems possible that the encoder counts drift over time.
Another solution is to use no prescalers, but instead extend the 16 bit value into the 32 bit space using the approach suggested here. I have reprinted the approach here in case the link goes dead:
From user goosen.kobus.001 on 11/19/2013 on ST's forum:
In my experience using an overflow interrupt to scale up an encoder is not reliable, especially when you have high resolution encoders: it happens from time to time that the encoder value will change sign in the instant you enter the interrupt, causing the system to increment the upper word when it should have decremented etc. This is especially true if the encoder is supposed to be stalled at 0, like a servo motor commanded to go to encoder position 0.
The best approach I have found is to do it manually. this is my procedure:
Ensure that the control loop that reads the encoder value is run often, (i.e. that if your encoder is rotating at full speed, the encoder value is still read at least 10-20 times between overflows. For my servo motor application a 1ms loop interval was sufficient.
keep track of the last read encoder value.
divide the current and last encoder value into quadrants (the most significant 2 bits). i.e. pos_now &= 0xC000; pos_last &= 0xC000;
check to see if the encoder has moved from quadrant 0 to quadrant 3 or 3 to 0 in the last step:
4.1 if(pos_now == 0 && pos_last == 0xC000) upper_word++;
4.2 if(pos_now == 0xC000 && pos_last == 0) upper_word--;
this is why I say the encoder read loop needs to be run often; you need to be sure that the value is read often enough that it is impossible to go from quadrant 0->1->2->3 in between reads.
It should also be possible to put this logic in another timer interrupt that runs at say 10kHz. that way you have an encoder value which is always up to date.
ST RESPONSE:
Hi,
I have got the feedback from the design and the architect of the timers.
The encoder interface has been designed to work without prescaler in order to not downgrade the resolution of the encoder.
As you observed, they have confirmed that it cannot work with even prescaler value but only the odd ones.
We have a sub-counter for the prescaler which is mono-directional, so not affected by the counter direction and incremented on every rising edge of the timer clock (without the prescaler).
The counter direction is updated on every rising edge of the timer clock (without the prescaler) but the counter is incremented only while the sub-counter of the prescaler reach the programmed value and according to the value in the direction bit.
So, in one case, the behavior is the same as without prescaler, because the counter is updated with a different direction (every odd clock cycles number), but in the other case, the direction is always the same when the counter is updated and the encoder interface doesn't work correctly.
So you can use the prescaler but with an odd value.
The recommended use case is without prescaler.
Best regards
ST MCU Tech Support
I am trying to program a MSP430 with a simple "FIR filter" program, that looks like the following:
#include "msp430x22x4.h"
#include "legacymsp430.h"
#define FILTER_LENGTH 4
#define TimerA_counter_value 12000 // 12000 counts/s -> 12000 counts ~ 1 Hz
int i;
double x[FILTER_LENGTH+1] = {0,0,0,0,0};
double y = 0;
double b[FILTER_LENGTH+1] = {0.0338, 0.2401, 0.4521, 0.2401, 0.0338};
signed char floor_and_convert(double y);
void setup(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
BCSCTL1 = CALBC1_8MHZ; // Set DCO
DCOCTL = CALDCO_8MHZ;
/* Setup Port 3 */
P3SEL |= BIT4 + BIT5; // P3.4,5 = USART0 TXD/RXD
P3DIR |= BIT4; // P3.4 output direction
/* UART */
UCA0CTL1 = UCSSEL_2; // SMCLK
UCA0BR0 = 0x41; // 9600 baud from 8Mhz
UCA0BR1 = 0x3;
UCA0MCTL = UCBRS_2;
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
/* Setup TimerA */
BCSCTL3 |= LFXT1S_2; // LFXT1S_2: Mode 2 for LFXT1 = VLO
// VLO provides a typical frequency of 12kHz
TACCTL0 = CCIE; // TACCR0 Capture/compare interrupt enable
TACCR0 = TimerA_counter_value; // Timer A Capture/Compare 0: -> 25 Hz
TACTL = TASSEL_1; // TASSEL_1: Timer A clock source select: 1 - ACLK
TACTL |= MC_1; // Start Timer_A in up mode
__enable_interrupt();
}
void main(void) // Beginning of program
{
setup(); // Call Function setup (see above)
_BIS_SR(LPM3_bits); // Enter LPM0
}
/* USCIA interrupt service routine */
/*#pragma vector=USCIAB0RX_VECTOR;*/
/*__interrupt void USCI0RX_ISR(void)*/
interrupt (USCIAB0RX_VECTOR) USCI0RX_ISR(void)
{
TACTL |= MC_1; // Start Timer_A in up mode
x[0] = (double)((signed char)UCA0RXBUF); // Read received sample and perform type casts
y = 0;
for(i = 0;i <= FILTER_LENGTH;i++) // Run FIR filter for each received sample
{
y += b[i]*x[i];
}
for(i = FILTER_LENGTH-1;i >= 0;i--) // Roll x array in order to hold old sample inputs
{
x[i+1] = x[i];
}
while (!(IFG2&UCA0TXIFG)); // Wait until USART0 TX buffer is ready?
UCA0TXBUF = (signed char) y;
TACTL |= TACLR; // Clear TimerA (prevent interrupt during receive)
}
/* Timer A interrupt service routine */
/*#pragma vector=TIMERA0_VECTOR;*/
/*__interrupt void TimerA_ISR (void)*/
interrupt (TIMERA0_VECTOR) TimerA_ISR(void)
{
for(i = 0;i <= FILTER_LENGTH;i++) // Clear x array if no data has arrived after 1 sec
{
x[i] = 0;
}
TACTL &= ~MC_1; // Stops TimerA
}
The program interacts with a MatLab code, that sends 200 doubles to the MSP, for processing in the FIR filter. My problem is, that the MSP is not able to deal with the doubles.
I am using the MSPGCC to compile the code. When I send a int to the MSP it will respond be sending a int back again.
Your problem looks like it is in the way that the data is being sent to the MSP.
The communications from MATLAB is, according to your code, a sequence of 4 binary byte values that you then take from the serial port and cast it straight to a double. The value coming in will have a range -128 to +127.
If your source data is any other data size then your program will be broken. If your data source is providing binary "double" data then each value may be 4 or 8 bytes long depending upon its internal data representation. Sending one of these values over the serial port will be interpreted by the MSP as a full set of 4 input samples, resulting in absolute garbage for a set of answers.
The really big question is WHY ON EARTH ARE YOU DOING THIS IN FLOATING POINT - on a 16 bit integer processor that (many versions) have integer multiplier hardware.
As Ian said, You're taking an 8bit value (UCA0RXBUF is only 8 bits wide anyway) and expecting to get a 32bit or 64 bit value out of it.
In order to get a proper sample you would need to read UCA0RXBUF multiple times and then concatenate each 8 bit value into 32/64 bits which you then would cast to a double.
Like Ian I would also question the wisdom of doing floating point math in a Low power embedded microcontroller. This type of task is much better suited to a DSP.
At least you should use fixed point math, seewikipedia (even in a DSP you would use fixed point arithmetic).
Hmm. Actually the code is made of my teacher, I'm just trying to make it work on my Mac, and not in AIR :-)
MATLAB code is like this:
function FilterTest(comport)
Fs = 100; % Sampling Frequency
Ts = 1/Fs; % Sampling Periode
L = 200; % Number of samples
N = 4; % Filter order
Fcut = 5; % Cut-off frequency
B = fir1(N,Fcut/(Fs/2)) % Filter coefficients in length N+1 vector B
t = [0:L-1]*Ts; % time array
A_m = 80; % Amplitude of main component
F_m = 5; % Frequency of main component
P_m = 80; % Phase of main component
y_m = A_m*sin(2*pi*F_m*t - P_m*(pi/180));
A_s = 40; % Amplitude of secondary component
F_s = 40; % Frequency of secondary component
P_s = 20; % Phase of secondary component
y_s = A_s*sin(2*pi*F_s*t - P_s*(pi/180));
y = round(y_m + y_s); % sum of main and secondary components (rounded to integers)
y_filt = round(filter(B,1,y)); % filtered data (rounded to integers)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Serial_port_object = serial(comport); % create Serial port object
set(Serial_port_object,'InputBufferSize',L) % set InputBufferSize to length of data
set(Serial_port_object,'OutputBufferSize',L) % set OutputBufferSize to length of data
fopen(Serial_port_object) % open Com Port
fwrite(Serial_port_object,y,'int8'); % send out data
data = fread(Serial_port_object,L,'int8'); % read back data
fclose(Serial_port_object) % close Com Port
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
subplot(2,1,1)
hold off
plot(t,y)
hold on
plot(t,y_filt,'r')
plot(t,y_filt,'ro')
plot(t,data,'k.')
ylabel('Amplitude')
legend('y','y filt (PC)','y filt (PC)','y filt (muP)')
subplot(2,1,2)
hold off
plot(t,data'-y_filt)
hold on
xlabel('time')
ylabel('muP - PC')
figure(1)
It is also not advised to keep interrupt routines doing long processing routines, because you will impact on interrupt latency. Bytes comming from the PC can get easily lost, because of buffer overrun on the serial port.
The best is to build a FIFO buffer holding a resonable number of input values. The USCI routine fills the FIFO while the main program keeps looking for data inside it and process them as they are available.
This way, while the data is being processed, the USCI can interrupt to handle new incomming bytes.
When the FIFO is empty, you can put the main process in a suitable LPM mode to conserve power (and this is the best MSP430 feature). The USCI routine will wake the CPU up when a data is ready (just put the WAKEUP attribute in the USCI handler if you are using MSPGCC).
In such a scenario be sure to declare volatile every variable that are shared between interrupt routines and the main process.