vTaskStartScheduler() overwrites the pointer param values, how to avoid that? - freertos

I have created a freeRTOS task, and passed a pointer of a struct as the function param.
I noticed the struct property was changed after vTaskStartScheduler()
How do I protect my struct?
Here is the code
Main
xTaskCreate(
SHELL_Main, // function the task calls
"shell", // nametag for debug console
512, // assigned buffersize
&user_context,// Parameter passed in
1, // task priority
NULL); //task handle
printf("exit=%i", (&user_context)-> exit);
vTaskStartScheduler();
SHELL_Main()
int32_t SHELL_Main(p_shell_context_t context)
{
printf("entered shell_main\n");
uint8_t ch;
int32_t i;
if (!context)
{
return -1;
}
context->exit = false;
context->printf_data_func("\r\nSHELL (build: %s)\r\n", __DATE__);
context->printf_data_func("Copyright (c) 2017 NXP Semiconductor\r\n");
context->printf_data_func(context->prompt);
while (1)
{
printf("context.exit=%s", (context->exit)?"true\n":"false\n");
printf("context.exit=%i", (context->exit));
if (context->exit)
{
printf("wtf");
break;
}
...
Here is the console
exit=0entered shell_main
SHELL (build: Oct 26 2018)
Copyright (c) 2017 NXP Semiconductor
SHELL>> context.exit=true
context.exit=253wtf
If I call SHELL_Main() directly in main instead of wrapping it in task, here's the console
exit=0entered shell_main
SHELL (build: Oct 26 2018)
Copyright (c) 2017 NXP Semiconductor
SHELL>> context.exit=false
context.exit=0
I speculate there is an overflow somewhere that overwrites my context.exit after calling vTaskStartScheduler(), but I do not know how to protect my struct. Can someone kindly share some idea?

SHELL_Main is what modifies your struct (context->exit = false;). You create that task and pass context to it as param. When you start the scheduler, that task gets run and sets it to false.
In fact vTaskStartScheduler() never returns. See doc here: https://www.freertos.org/a00132.html
From comments below, sounds like printf_data_func() is causing the issues. Dig further into it.

[This question is old, but I'm adding an answer since it came up in Google search results]
You haven't included the definition of user_context in main(), but I suspect it's a local. Some ports of FreeRTOS repurpose main()'s stack space for use by interrupts, so you can't rely on local variables surviving the call to vTaskStartScheduler(). Making user_context static should solve the problem. See this FreeRTOS FAQ.

Related

How does addressing work in devicetree for a Xilinx CDMA?

Background:
What I want to do is to be able to write from my ARM processor to a BRAM, on a Zynq 7000.
To do this, I have the following components:
-M_AXI_GP0 on PS7 connects to S_AXI_LITE on axi_cdma_0 through an AXI Interconnect
-cdma_introut on axi_cdma_0 connects to IRQ_F2P on PS7 through sys_concat, input 11. This means that this maps to Interrupt 87 on PS7.
-M_AXI on axi_cdma_0 connects to S00_AXI on axi_mem_intercon
-M01_AXI on axi_mem_intercon connects to S_AXI_HP3 on PS7
-M00_AXI on axi_mem_intercon connects to S_AXI on axi_bram_ctrl_0
-BRAM_PORTA on axi_bram_ctrl_0 connects to BRAM_PORTA on blk_mem_gen0
=========================================================================
In my mind, what this setup ought to do is this:
Once a transaction is submitted from the ARM DMA Engine, the Zynq will use GP0 to send a command to the CDMA controller via GP0.
The CDMA controller will receive the commands on its slave AXI_LITE port, and interpret the request to access RAM via HP3.
The CDMA controller will move data through axi_mem_intercon in order to take the transaction data from hp3 on M01_AXI, and send it through M00_AXI to the BRAM Controller
The BRAM controller will take in the AXI-4 input and convert that to the appropriate BRAM port to write the data into the BRAM generated by blk_mem_gen_0
After completing this action, the CDMA will send an interrupt through sys_concat to indicate to the DMA Engine that its work is complete.
After loading this hdl design into the PL fabric, I attempt to submit the transaction to the DMA engine via a kernel module. The result is a timeout, with the DMA engine apparently never finishing the task.
=========================================================================
In my attempts to figure out the problem, I've made these observations:
After attempting a write transaction, which times out, I attempted a read transaction to the same DMA channel, but configured to read data. What I get back is all the data that I had attempted to write. This, to me, seems to indicate that the DMA engine IS writing to somewhere, but isn't recognizing the completion of the task
The BRAM in question is a dual port RAM, and the other port reads the data in the BRAM and toggles LEDs to reflect the data. The LEDs are not toggling when I attempt this write transaction, so it seems as though the DMA transaction is not making it as far as the BRAM
When looking at cat /proc/interrupts, I can see several interrupts, but not GIC 87. As mentioned before, the interrupt line I am using goes to Input 11 of the IRQ concat block. I can confirm that the interrupt line which goes to Input 12 does indeed correspond to GIC 88 from /proc/interrupts, so I believe my understanding of which interrupt I am looking for is correct. So for some reason it is not registering that interrupt on the processor.
=========================================================================
Based on this, I believe my devicetree entry for this CDMA is what is incorrect.
In Vivado, I can see these entries in the Address Editor(Some entries omitted for brevity):
sys_ps7
Data(32 address bits:0x40000000 [1G])
axi_cdma_0 S_AXI_LITE Reg 0x43C0_0000 64K 0x43C0_FFFF
axi_cdma_0
Data(32 address bits : 4G)
axi_bram_ctrl_0 S_AXI Mem0 0xC000_0000 4K 0xC000_0FFF
sys_ps7 S_AXI_HP3 HP3... 0x0000_0000 1G 0x3FFF_FFFF
My attempt to write a devicetree entry is as follows:
axi-cdma#43C00000{
#dma-cells = <0x1>;
compatible = "tst,axi-cdma-ctrl-1.00.a";
reg = <0x10000000 0x1000>;
interrupts = <0x0 0x37 0x4>;
interrupt-parent = <0x1>;
dma-channel#C0000000{
buswidth = <0x20>;
}
Before I added this entry in my kernel module failed to even register a transaction channel, and now it does, so I am fairly certain that the kernel is accepting this entry at least enough to assign a DMA channel. However, I don't understand much about how exactly the devicetree works, specifically with the addressing, so there is a good chance I have written this incorrectly, and that is why my transaction doesn't succeed. Can anyone help me correct my design?
}
Declaring the IP core in device tree is not sufficient. You must also declare your DMA client, as Xilinx does in CDMA test client:
cdmatest_1: cdmatest#1 {
compatible ="xlnx,axi-cdma-test-1.00.a";
dmas = <&axi_cdma_0 0>;
dma-names = "cdma";
} ;
In dmas field, the axi_cdma_0 references the CDMA IP core and the 0 its first dma-channel, as defined in the devicetree:
axi_cdma_0: dma#4e200000 {
#dma-cells = <1>;
clock-names = "s_axi_lite_aclk", "m_axi_aclk";
clocks = <&clkc 15>, <&clkc 15>;
compatible = "xlnx,axi-cdma-1.00.a";
interrupt-parent = <&intc>;
interrupts = <0 31 4>;
reg = <0x4e200000 0x10000>;
xlnx,addrwidth = <0x20>;
xlnx,include-sg ;
dma-channel#4e200000 {
compatible = "xlnx,axi-cdma-channel";
interrupts = <0 31 4>;
xlnx,datawidth = <0x20>;
xlnx,device-id = <0x0>;
xlnx,include-dre ;
xlnx,max-burst-len = <0x10>;
};
};
After that, you should register your client as a platform driver. Again, from CDMA test client source:
static const struct of_device_id xilinx_cdmatest_of_ids[] = {
{ .compatible = "xlnx,axi-cdma-test-1.00.a", },
{ }
};
static struct platform_driver xilinx_cdmatest_driver = {
.driver = {
.name = "xilinx_cdmatest",
.owner = THIS_MODULE,
.of_match_table = xilinx_cdmatest_of_ids,
},
.probe = xilinx_cdmatest_probe,
.remove = xilinx_cdmatest_remove,
};
static int __init cdma_init(void)
{
return platform_driver_register(&xilinx_cdmatest_driver);
}
Please note the compatible field of device tree and of platform driver definition, these strings must match. If you did not do this, the dma_request_slave_channel() cannot reserve a channel from your CDMA IP core. Moreover, ensure you do not use dma_request_channel() which is not supported in xilinx kernel >= 4.0 and will fail to reserve channels properly, the transfer will not complete and the DMA will timeout with no interrupt. I am not sure about observation 1, it might be a caching effect. Try to use dma_alloc_coherent() instead of kmalloc().
PS: In any case, try to make sure your hardware is ok by using a bare metal app if possible.

JSR 352: Is there a way to tell if a particular job execution is a restart or not from within a job?

I know how to get the Execution Id and Instance Id of a job using the Job Context. But if i restart a job, is there way to know if the job execution is the first execution or a restart within the job, for instance inside the reader?
No, but there is an open issue asking for that:
https://java.net/bugzilla/show_bug.cgi?id=7473
This is a bit overly complicated (as the other answer noted, there's an issue opened to consider enhancement for the future Batch 1.1).
You could do this:
//
// Assumes JobContext injected into 'jobCtx' field
//
private boolean isRestart() {
JobOperator jo = BatchRuntime.getJobOperator();
JobInstance jobInstance = jo.getJobInstance(jobCtx.getExecutionId());
int numExecutions = jo.getJobExecutions(jobInstance).size();
return numExecutions > 1;
}

Optimizing Lua for cyclic execution

I'm exeucting my Lua script once per program cycle of 10 ms. using the same Lua_state (luaL_newstate called once in my app)
Calling luaL_loadbuffer complies the script very fast for sure, still it seems unneccessary to do this every time the script is executed since the script does not change.
Tried to save binary using lua_dump() and then execute it, but lua_pcall() didn't accept the binary for some reason.
Any ideas on how to optimize? (LuaJIT is not an unfortenately an option here)
Jan
You're correct, if the code is not changing, there is no reason to reprocess the code. Perhaps you could do something like the following:
luaL_loadbuffer(state, buff, len, name); // TODO: check return value
while (true) {
// sleep 10ms
lua_pushvalue(state, -1); // make another reference to the loaded chunk
lua_call(state, 0, 0);
}
You'll note that we simply duplicate the function reference on the top of the stack, since lua_call removes the function that it calls from the stack. This way, you do not lose a reference to the loaded chunk.
Executing the loadbuffer compiles the script into a chunk of lua code, which you can treat as an anonymous function. The function is put at the top of the stack. You can "save" it the way you would any other value in Lua: push a name for the function onto the stack, then call lua_setglobal(L, name). After that, every time you want to call your function (the chunk), you push it onto the Lua stack, push the parameters onto the stack, and call lua_pcall(L, nargs, nresults). Lua will pop the function and put nresults results onto the stack (regardless of how many results are returned by your function -- if more are returned they are discarded, if fewer then the extras are nil). Example:
int stat = luaL_loadbuffer(L, scriptBuffer, scriptLen, scriptName);
// check status, if ok save it, else handle error
if (stat == 0)
lua_setglobal(L, scriptName);
...
// re-use later:
lua_getglobal(L, scriptName);
lua_pushinteger(L, 123);
stat = lua_pcall(L, 1, 1, 0);
// check status, if ok get the result off the stack

How do you run an interactive process in Dart?

The test below attempts to run the less pager command and return once
the user quits. The problem is that it doesn't wait for user input, it
just lists the entire file and exits. Platform: xubuntu 12.04, Dart
Editor build: 13049.
import 'dart:io';
void main() {
shell('less', ['/etc/mime.types'], (exitCode) => exit(exitCode));
}
void shell(String cmd, List<String> opts, void onExit(int exitCode)) {
var p = Process.start(cmd, opts);
p.stdout.pipe(stdout); // Process output to stdout.
stdin.pipe(p.stdin); // stdin to process input.
p.onExit = (exitCode) {
p.close();
onExit(exitCode);
};
}
The following CoffeeScript function (using nodejs I/O) works:
shell = (cmd, opts, callback) ->
process.stdin.pause()
child = spawn cmd, opts, customFds: [0, 1, 2]
child.on 'exit', (code) ->
process.stdin.resume()
callback code
How can I make this work in Dart?
John has a good example about how to look at user input. But doesn't answer your original question. Unfortunately your question doesn't fit with how Dart operates. The two examples you have, the Dart version and CoffeeScript/Node.js version, do two completely different things.
In your CoffeeScript version, the spawn command is actually creating a new process and then passing execution over to that new process. Basically you're program is not interactively communicating with the process, rather your user is interacting with the spawned process.
In Dart it is different, your program is interacting with the spawned process. It is not passing off execution to the new process. Basically what you are doing is piping the input/output to and from the new process to your program itself. Since your program doesn't have a 'window height' from the terminal, it passes all the information at once. What you're doing in dart is almost equivalent to:
less /etc/mime.types | cat
You can use Process.start() to interactively communicate with processes. But it is your program which is interactively communicating with the process, not the user. Thus you can write a dart program which will launch and automatically play 'zork' or 'adventure' for instance, or log into a remote server by looking at the prompts from process's output.
However, at current there is no way to simply pass execution to the spawned process. If you want to communicate the process output to a user, and then also take user input and send it back to a process it involves an additional layer. And even then, not all programs (such as less) behave the same as they do when launched from a shell environment.
Here's a basic structure for reading console input from the user. This example reads lines of text from the user, and exits on 'q':
import 'dart:io';
import 'dart:isolate';
final StringInputStream textStream = new StringInputStream(stdin);
void main() {
textStream.onLine = checkBuffer;
}
void checkBuffer(){
final line = textStream.readLine();
if (line == null) return;
if (line.trim().toLowerCase() == 'q'){
exit(0);
}
print('You wrote "$line". Now write something else!');
}

Is it possible to pass command-line arguments to a new isolate from spawnUri()

When starting a new isolate with spawnUri(), is it possible to pass command line args into that new isolate?
eg: Command line:
dart.exe app.dart "Hello World"
In app.dart
#import("dart:isolate");
main() {
var options = new Options();
print(options.arguments); // prints ["Hello World"]
spawnUri("other.dart");
}
In other.dart
main() {
var options = new Options();
print(options.arguments); // prints [] when spawned from app.dart.
// Is it possible to supply
// Options from another isolate?
}
Although I can pass data into other.dart through its SendPort, the specific use I want is to use another dart app that hasn't been created with a recievePort callback (such as pub.dart, or any other command-line app).
As far as I can tell the answer is currently no, and it would be hard to simulate via message passing because the options would not be available in main().
I think there are two good feature requests here. One is to be able to pass options on spawn() so that a script can run the same from the root isolate or a spawned isolate.
The other feature, which could be used to implement the first, is a way to pass messages that are handled by libraries before main() is invoked so that objects that main() depends on can be initialized with data from the spawning isolate.
Your example doesn't call print(options.arguments); in other.dart using the current stable SDK.
However
spanUri("other.dart");
spawns an Uri. So how about spawnUri("other.dart?param=value#orViaHash"); and try if you can find the param/value pair via
print(options.executable);
print(options.script);

Resources