Doing a research on stackoveflow I have found this code:
asm(
"lock\n\t"
"xadd %1, %0":
"+m"( mem), "=r"(r):
"1"( val ):
"memory", "cc");
The lock instruction is there to ensure atomicity in case of concurrent access, now the xadd adds the content of the two regiters and put the result in the first one.
However I don't understand the rest of the code : If mem = r then increment the memory content with (val) in this case 1. Does r refer to the expected value ? Can any of these values be returned using a simple return, return mem for example. Is the xadd operation intel specific ?
Related
I'm doing my first attempt working with linker files. In the end i want to have a variable that keeps it's value after reset. I'm working with an STM32L476.
To achieve this i modified the Linker files: STM32L476JGYX_FLASH.ld and STM32L476JGYX_RAM.ld to include a partition called NOINT.
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K
RAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 32K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K -0x100
NOINIT (rwx) : ORIGIN = 0x8000000 + 1024K - 0x100, LENGTH = 0x100
}
/* Sections */
SECTIONS
{
...
/* Global data not cleared after reset. */
.noinit (NOLOAD): {
KEEP(*(*.noinit*))
} > NOINIT
...
In the main.c i initialize the variable reset_count as a global variable.
__attribute__((section(".noinit"))) volatile uint32_t reset_count = 0;
The =0 part is just for simplification. I actually want to set reset_count to zero somewhere in a function.
When i run the program and step through the initialization i would expect to see the value of reset_count as 0. But somehow i always get 0xFFFFFFFF. It seems like i can't edit the reset_count variable. Can anybody tell me how i can make this variable editable?
It is not clear from the question whether you want to have a variable that keeps its value when power is removed, or just while power stays on but hardware reset is pulsed.
If you want something that keeps its value when power is removed, then your linker script is ok to put the block in flash memory, but you need to use the functions HAL_FLASH_Program etc. to write to it, you can't just make an assignment. In addition, you could simplify the linker script by instead of creating the NOINIT output region, just putting >FLASH.
If you want a variable that just persists across reset wile power stays up then you need to put the variable into SRAM not FLASH, for example like this:
.noinit (NOLOAD) :
{
*(.noinit*)
}
> RAM2
Note that you don't need to use KEEP unless you want to link a section that is unreferenced, which will not be the case if you actually use the variables, and you don't need another * immediately before .noinit unless you section names don't start with a ., which they should.
You will not be able to write to the flash memory as simply as that. If you use ST HAL, there is a flash module that provides HAL_FLASH_Program() function.
Alternatively, if the data you are trying to store is 128 bytes or less and you have an RTC backup battery, you can use the RTC backup registers (RTC_BKPxR) to store your data.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm currently working with 9S12 from freescale, I really need some help in order to understand how to write correctly an ISR. In particular, I'm reporting the text of an exercise in which they asked me to measure the difference in phase between two square waveforms (at the input of the microcontroller).
The bus clock is 16 MHz and I have to use the timer module of the system, which provides a free-running counter (TCNT # 16 bit). The counter have to work # 500 kHz, that is achieved by setting a prescaler of 5, starting from the bus clock.
The two signals have the same frequency, which is given (25 Hz), but is required to measure it anyway.
I have to use the INTERRUPT procedure, using the correct registers (actually is not necessary using the exact same ones from the manual, I can use any names I want, instead I have to comment every line of the code) and variables.
My way of approaching the problem is very theoretical, but I need the C code.
In order to solve the problem I have to use the INPUT CAPTURE MODE, to measure the difference in term of units counted by the TCNT (TICKS) between the positive edge of signal 1 and the positive edge of signal 2. My doubts are in particular on the variables that I have to use, the type (LOCAL, GLOBAL, UNSIGNED, LONG (?)), how can I update the values correctly in the ISR and if I should take into account of the overflows of the counter and the respective interrupts generated by them.
I'm stuck in this problem, I hope someone can help me with some code examples in particular for the variables that I have to use and how to write the actual ISR.
Thank you to everyone!
Treat the following as pseudo-code; it is for you to wade through the datasheet to determine how to configure and access the timer-capture unit - I am not familiar with the specific part
In general, given the timer-counter is 16 bit:
volatile static uint16_t phase_count = 0 ;
volatile static uint16_t mean_period_count = 0 ;
int phasePercent()
{
(phase_count * 100) / mean_period_count ;
}
int frequencyHz()
{
500000 / mean_period_count ;
}
void TimerCounterISR( void )
{
static uint16_t count1 = 0 ;
static uint16_t count2 = 0 ;
static uint16_t period1 = 0 ;
static uint16_t period2 = 0 ;
uint16_t now = getCaptureCount() ;
if( isSignal1Edge() )
{
period1 = now - count1 ;
count1 = now ;
}
else if( isSignal2Edge() )
{
period2 = now - count2 ;
count2 = now ;
phase_count = period2 - period1 ;
}
mean_period_count = (period1 + period2) >> 1 ;
}
The method assumes an up-counter and requires that the counter reload runs the full 16 bit range 0 to 0xFFFF - otherwise the modulo-216 arithmetic will not work, and the solution will be much more complex. For a down-counter, swap the operands in the period calculations.
Note the return value from phasePercent() and frequencyHz() will not be valid until after a complete rising-edge to rising-edge cycle on both phases. You could add an edge count and validate after the rising edge has been seen twice on each signal if that is an issue.
This is how you sort out the technical parts for the S12:
Setup the ECT timer with appropriate pre-scaler. You seem to have this part covered? At 500kHz each timer tick is 2us and you need 65536 timer ticks to cover the worst case. One full TCNT period will be 131ms with your prescaler. If ~25Hz is the worst case, then that's roughly 40ms so it should be ok in that case.
Pick a timer channel TC that corresponds to the pin used. This channel needs to be configured as input capture, trigger on both rising/falling edge. Store the current value of TCNT as init value to a uint16_t time counter variable.
Register the ISR in the vector table etc, the usual stuff for writing an ISR.
Upon interrupt, read the value of the TCn channel register. The difference between the counter variable and the stored value gives the period time in timer cycles. Multiply this with 1/500kHz and you get the period time. In the ISR always read TC and not TCNT, as the former will not be affected by interrupt latency and code execution overhead. Update your counter variable with the value from TCn.
With a design like this ensure there are some external means of filtering out spikes and EMI from the input: RC filter or similar.
I am working with PLCs trying to design a water tank. On one section of the design I am asked to create a clock pulse generator. I am currently trying to do this using ladder diagrams.
I believe I have the logic correct just cant seem to put it together. I want a counter to count the clock pulses that I generate, then I store these pulese in a data memory to ensure the count is retained if the system is switched off and on.
question is how do I design this clock pulse generator.
Kind regards
There are a few different ways to create a pulse generator (or commonly known in the plc world as a BLINK timer). As a matter of fact many plc programming softwares have this function block built in to their function block libraries. But if they don't or you just want to make your own you can do something like this
VAR
ton1: TON;
ton2: TON;
StartPulse: BOOL;
startPulseTrig: R_TRIG;
LatchPulseInitial: BOOL;
PulseOutput: BOOL;
Timer1Done: BOOL;
Timer2Done: BOOL;
PulseWidth:TIME:=t#500ms;
END_VAR
If you would like to count the number of pulses and store this value to a variable you can use a simple CTU (counter up) block available in all plc languages.
Review of functionality
The StartPulse variable can be anything you want that will start the counter. In my case I just used an internal bool variable that I turned on. If you want this timer to start automatically when the plc starts then just initialize this variable to true. Because StartPulse only works on the rising edge of the signal the LatchPulseInitial coil will only ever be set once.
When the LatchPulseInitial variable goes true this will start ton1 a Timer On Delay (TON) function block. This will delay the output of the block from turning on for the time of PT (in my case I have 500ms).
After 500ms has expired the ton1 outputs will turn on. this will turn on the Timer1Done variable and turn off the Timer2Done and LatchPulseInitial. Now that LatchPulseInitial has been turned off it will never interfere with the program again since it can only be turned on by the rising edge of StartPulse. Note: once the block has reached PT the outputs will stay on until the input to the block is removed.
Since Timer1Done is now on ton2 will start counting until PT is reached. Once PT is reached the outputs for that block will turn on. This will reset Timer1Done and set Timer2Done This will start ton1 again and thus starting the whole process over.
For the PulseOutput, which is the actual pulse output you are looking for, I have this being set to true when Timer2Done is true. This is because when this variable is true it is the high state of the pulse generator. When Timer1Done is true it is the low state of the pulse generator.
When the PulseOutput goes true it will trigger the input on the CTU which will increment the count of the variable in CV (current value) by 1.
If you are going to be using this logic in numerous places in your program or you plan on reusing it in the future I would make this into its own function block so you won't have to repeat this logic everytime you want to make this type of timer.
Once I had to create a BLINK FB. It is written in Structured Text. But it is suitable to use in a ladder logic program and IN/OUT Variables are named like TON style. The Blink starts with Q = TRUE. If you want to start with FALSE just invert Q and switch the Times!
FUNCTION_BLOCK BLINK
VAR_INPUT
IN : BOOL;
PT_ON : TIME;
PT_OFF : TIME;
END_VAR
VAR_OUTPUT
Q : BOOL;
ET : TIME;
END_VAR
VAR
rtIN : R_TRIG;
tonBlink : TON;
END_VAR
rtIN(CLK := IN);
IF tonBlink.Q OR rtIN.Q THEN
(*Toggle Output*)
Q := NOT Q;
(*Timer Reset call, important to call timer twice in same cycle for correct Blink Time*)
tonBlink(IN:= FALSE);
(*Set corresponding Time*)
IF Q THEN
tonBlink.PT := PT_ON;
ELSE
tonBlink.PT := PT_OFF;
END_IF
END_IF
(*Timer Run call*)
tonBlink(IN:= IN);
IF IN THEN
ET := tonBlink.ET;
ELSE
ET := T#0S;
Q := FALSE;
END_IF
In my opinion, this is the most straightforward way to do it, using 1 timer, up counter and modulo operator:
Blink function in ladder
Also note, if your PLC doesnt have modulo, then multiply by -1 each time.
I'm writing Ragel machine for rather simple binary protocol, and what I present here is even more simplified version, without any error recovery whatsoever, just to demonstrate the problem I'm trying to solve.
So, the message to be parsed here looks like this:
<1 byte: length> <$length bytes: user data> <1 byte: checksum>
Machine looks as follows:
%%{
machine my_machine;
write data;
alphtype unsigned char;
}%%
%%{
action message_reset {
/* TODO */
data_received = 0;
}
action got_len {
len = fc;
}
action got_data_byte {
/* TODO */
}
action message_received {
/* TODO */
}
action is_waiting_for_data {
(data_received++ < len);
}
action is_checksum_correct {
1/*TODO*/
}
len = (any);
fmt_separate_len = (0x80 any);
data = (any);
checksum = (any);
message =
(
# first byte: length of the data
(len #got_len)
# user data
(data when is_waiting_for_data #got_data_byte )*
# place higher priority on the previous machine (i.e. data)
<:
# last byte: checksum
(checksum when is_checksum_correct #message_received)
) >to(message_reset)
;
main := (msg_start: message)*;
# Initialize and execute.
write init;
write exec;
}%%
As you see, first we receive 1 byte that represents length; then we receive data bytes until we receive needed amount of bytes (the check is done by is_waiting_for_data), and when we receive next (extra) byte, we check whether it is a correct checksum (by is_checksum_correct). If it is, machine is going to wait for next message; otherwise, this particular machine stalls (I haven't included any error recovery here on purpose, in order to simplify diagram).
The diagram of it looks like this:
$ ragel -Vp ./msg.rl | dot -Tpng -o msg.png
Click to see image
As you see, in state 1, while we receiving user data, conditions are as follows:
0..255(is_waiting_for_data, !is_checksum_correct),
0..255(is_waiting_for_data, is_checksum_correct)
So on every data byte it redundantly calls is_checksum_correct, although the result doesn't matter at all.
The condition should be as simple: 0..255(is_waiting_for_data)
How to achieve that?
How is is_checksum_correct supposed to work? The when condition happens before the checksum is read, according to what you posted. My suggestion would be to check the checksum inside message_received and handle any error there. That way, you can get rid of the second when and the problem would no longer exist.
It looks like semantic conditions are a relatively new feature in Ragel, and while they look really useful, maybe they're not quite mature enough yet if you want optimal code.
My question is how to create a dynamic pool of workers with MPI.
There is a large (NNN = 10^6-7 elements) 1D array/vector. I should perform some calculations on each cell. This problem is extremely embarrassingly parallel.
The idea is (it works fine): each MPI process (when run in parallel) reads common .dat file, puts values in local (to each rank) large vector of size NNN and performs computation on appropriate part of large array, the lenght of this "part" is NNN/nprocs, where "nprocs" is the number of processes of MPI.
The problem: some "parts" of this array (NNN/nprocs) are finished very quick and thus some of CPUs are unused (they wait for the others to finish the run).
The question1: How to make dynamic schedule. CPU's, that finished their tasks, can pick new task and continue working.
The question2: Is there MPI built-in procedure, that schedules automatically "workers" and tasks?
Here is my code (static schedule)
{
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Offset offset;
MPI_File file;
MPI_Status status;
int Pstart = (NNN / nprocs) * rank + ((NNN % nprocs) < rank ? (NNN % nprocs) : rank);
int Pend = Pstart + (NNN / nprocs) + ((NNN % nprocs) > rank);
offset = sizeof(double)*Pstart;
MPI_File_open(MPI_COMM_WORLD, "shared.dat", MPI_MODE_CREATE|MPI_MODE_WRONLY, MPI_INFO_NULL, &file);
double * local_array;
local_array = new double [NNN/nprocs];
for (int i=0;i<NNN/nprocs;i++)
{
/* next line calculates integral on each cell element of part NNN/nprocs of large array NNN */
adapt_integrate(1, Integrand, par, 2, a, b, MaxEval, tol, tol, &val, &err);
// putting result of integration to local array NNN/nprocs
local_array[i] = val;
}
// here, all local arrays are written to one shared file "shared.dat"
MPI_File_seek(file, offset, MPI_SEEK_SET);
MPI_File_write(file, local_array, NNN/nprocs, MPI_DOUBLE, &status);
MPI_File_close(&file);
}
This question is about a similar problem, but just to recap: have a designated master process that issues chunks of work to the others. All the workers need to do is blocking receive a work item, perform their calculations, then blocking send the result to the master and repeat. The master can manage work items either by posting a nonblocking receive for each worker and polling if any of them completed, or by posting a blocking receive with MPI_ANY_SOURCE as source.