I am working on hypervisor with raspberry pi 4B board.
when I study interrupt virtualization, I encounter a problem, I am follow this document
[url]https://developer.arm.com/documentation/102142/0100/Virtualizating-exceptions[/url]
[quote]There are two mechanisms for generating virtual interrupts:
1 Internally by the core, using controls in HCR_EL2.
2 Using a GICv2, or later, interrupt controller.
[/quote]
I use method 1. Everything worked fine, I can route IRQ to my EL2 code, and I can forward it to EL1 Linux kernel.
But, when I tested, I tried to disable IRQ from EL1, use "msr daifset, #0xf", after this, IRQ will not trigger to EL2 also.
I am confused, because the document above said pstate.I will only affect vIRQ(for EL1) not pIRQ(EL2). I tested a GPIO interrupt and IPI interrupt, both failed.
I search the web, there are few article on this topic, and can't find any additional settings.
All document I found, said set I bit in EL1, will not affect EL2/3.
Thanks, if anyone can help.
There are two concepts involved in interrupt handling, interrupt routing and interrupt masking. Setting PSTATE.DAIF to 1, will mask the interrupt(but there are some conditions) and HCR_EL2.AMO,IMO,FMO will route the interrupt to EL2 from EL1 or EL0.
If you are at EL1/EL0, HCR_EL2.{IMO,FMO,AMO} are set to one then interrupts cannot be masked using PSTATE.DAIF bits. In this case interrupt will be delivered to EL2. Here it's assumed HCR_EL2.{E2H, TGE} are zero.
If you are at EL1/EL0, HCR_EL2.{IMO,FMO,AMO} are set to zero, then interrupts can be masked using PSTATE.DAIF bits.
If you are at EL2, HCR_El2.{IMO,FMO,AMO} are set to zero, irrespective of PSTATE.DAIF bits interrupt will not be delivered. If these are set to one then PSTATE.DAIF bits can mask the interrupt.
Similarly there are controls in SCR_EL3.{EA,IRQ,FIQ} which when set to one will route the interrupt to EL3 from EL2, EL1 or EL0. Above rules hold good here as well.
Related
I wanted to measure the energy consumption of my app using energest. However, I found out that the radio is almost always listening, as the RX energest value is pretty close to the Rtime interval I measure about. I want to ask you if I should use low-power-mode in the board, so that I force the radio to deactivate and result in less energy consumption. Can I use PM0 if I really need to use the RAM? I am asking you because the linker puts a comment in a header file that only PM1 can give access to the 32k RAM, and bypasses the defined macro: #define LPM_CONF_MAX_PM 0. Thank you.
By default, the CSMA MAC protocol is used in Contiki-NG. This protocol always has radio on. For radio duty cycling, either use TSCH, or turn off the radio from application's code by calling NETSTACK_RADIO.off().
I have been trying to set up a custom manipulation station with Kuka IIWA hardware in drake. I got the hardware interface working. When running a joint teleoperation code (adapted from drake/examples/manipulation_station/joint_teleop.py), the robot jerks violently (all joints tries to move to 0 position) at first and then continues to operate normally. On digging deeper, I found that this is caused by the FirstOrderLowPassFilter system. While advancing the simulation a tiny bit (simulator.AdvanceTo(1e-6)) to evaluate the LCM messages to set the initial GUI sliders-filter_initial_output_value-plant joint positions etc., to match the hardware, the FirstOrderLowPassFilter outputs a momentary value of 0. This sets the IIWA_COMMAND position to zero for an instance and causes a jerk.
How can I avoid this behavior?.
As a workaround, I am subscribing separately to the raw LCM message from the hardware, before initializing the drake systems and sets the filter_initial_output_value before advancing the simulation. Is this the recommended way?.
I think what you're doing (manually reading the LCM message) is fine.
In the alternative, look how a DiscreteDerivative offers the suppress_initial_transient = true option. Perhaps we could add a similar option (via unrestricted update event) to FirstOrderLowPassFilter so that the initial output value was sampled from the input at t == 0. But the event sequencing of startup may still be difficult. We essentially need to initialize the systems in their dataflow order, including refreshing output ports as events fire, which is not natively supported.
In another alternative, perhaps we could configure the IIWA_COMMAND publisher to not publish at t == 0, instead publishing only t >= 0.005.
FirstOrderLowPassFilter has a method to set the initial value. https://drake.mit.edu/doxygen_cxx/classdrake_1_1systems_1_1_first_order_low_pass_filter.html#aaef7539cfbf1acfa0cf487c371bc5360
It is used in the example that you copied from:
https://github.com/RobotLocomotion/drake/blob/master/examples/manipulation_station/joint_teleop.py#L146
I'm working on a dual OS system with STM32F103, I have two separate program that programmed on different FLASH locations. if both of the programs are the same, the only way to know which of them running is just by its start vector address.
But How I Can Read The Current Program Start Vector Address in STM32 ???
After reading the comments, it sounds like what you have/want is a bootloader. If your goal here is to have two different applications, one to do your main processing and real time handling and the other to just program new firmware, then you want to make a bootloader in your default boot flash space.
Bootloaders fundamentally do a few things, everything else is extra.
Check itself using some type of data integrity check like a CRC.
Checks the application
Jumps to the application.
Bootloaders will also program applications in the app space and verify they are programmed correctly before jumping as well. Colin gave some good advice about appending a CRC to the hex file before it is programmed in flash space to verify the applications.
There are a few things to look out for. The first would be the linker script and this is extremely important. A linker script will be used to map input objects to output objects and then determine based upon that script, what memory space they go into. For both of your applications, you need to create a memory map of how you want both programs to sit inside of the flash space. From this point, you can then make linker scripts for both programs so that a hex file can be generated within the parameters of what you deem acceptable flash space for the program. Each project you have will have its own linker script. An example would look something like this:
LR_IROM1 0x08000000 0x00010000 { ; load region size_region
ER_IROM1 0x08000000 0x00010000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x00018000 { ; RW data
.ANY (+RW +ZI)
}
}
This will give RAM for the application to use as well as a starting point for the application.
After that, you can start the bootloader and give it information about where the application space lies for jumping and programming. Once again this is all determined by you from your memory map and both applications' linker scripts. You are going to need to add a separate entry inside of the linker for your CRC and length for a comparison of the calculated versus stored as well. Whatever tool you use to append the CRC to the hex file and have it programmed to flash space, remember to note the location and make it known to the linker script so you can reference those addresses to check integrity later.
After you check everything and it is determined that it is okay to go to the application, you can use some ARM assembly to jump to the starting application address. Before jumping, make sure to disable all peripherals and interrupts that were enabled in the bootloader. As Colin mentioned, these will share RAM, so it is important you de-initialize all used, otherwise, you'll end up with a hard fault.
At this point, the program used another hex file laid out by a linker script, so it should begin executing as planned, as long as you have the correct vector table offset, which gets into your question fully.
As far as your question on the "Flash vector address", I think what your really mean is your interrupt vector table address. An interrupt vector table is a data structure in memory that maps interrupt requests to the addresses of interrupt handlers. This is where the PC register grabs the next available instruction address upon hardware interrupt triggers, for example. You can see this by keeping track of the ARM pipeline in a few lines of assembly code. Each entry of this table is a handler's address. This offset must be aligned with your application, otherwise you will never go into the main function and the program will sit in the application space, but have nothing to do since all handlers addresses are unknown. This is what the SCB->VTOR is for. It is a vector interrupt table offset address register. In this case, there are a few things you can do. Luckily, these are hard-coded inside of STM generated files inside of the file "system_stm32(xx)xx.c" (xx is your microcontroller variant). There is a define for something called VECT_TAB_OFFSET which is the offset in the memory map of the vector table and is assigned to the SCB->VTOR register with the value that is chosen. Your interrupt vector table will always lie at the starting address of your main application, so for the bootloader it can be 0x00, but for the application, it will be the subtraction of the starting address of the application space, and the first addressable flash address of the microcontroller.
/************************* Miscellaneous Configuration ************************/
/*!< Uncomment the following line if you need to relocate your vector Table in
Internal SRAM. */
/* #define VECT_TAB_SRAM */
#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
/******************************************************************************/
Make sure you understand what is expected from the micro side using STM documentation before programming things. Vector tables in this chip can only be in multiples of 0x200. But to answer your question, this address can be determined by a few things. Your memory map, and eventually, you will have a hard-coded reference to it as a define. You can figure it out from there.
Hope this helps and good luck to you on your application.
It seems that when an I/O pin interrupt occurs while network I/O is being performed, the system resets -- even if the interrupt function only declares a local variable and assigns it (essentially a do-nothing routine.) So I'm fairly certain it isn't to do with spending too much time in the interrupt function. (My actual working interrupt functions are pretty spartan, strictly increment and assign, not even any conditional logic.)
Is this a known constraint? My workaround is to disconnect the interrupt while using the network, but of course this introduces potential for data loss.
function fnCbUp(level)
lastTrig = rtctime.get()
gpio.trig(pin, "down", fnCbDown)
end
function fnCbDown(level)
local spin = rtcmem.read32(20)
spin = spin + 1
rtcmem.write32(20, spin)
lastTrig = rtctime.get()
gpio.trig(pin, "up", fnCbUp)
end
gpio.trig(pin, "down", fnCbDown)
gpio.mode(pin, gpio.INT, gpio.FLOAT)
branch: master
build built on: 2016-03-15 10:39
powered by Lua 5.1.4 on SDK 1.4.0
modules: adc,bit,file,gpio,i2c,net,node,pwm,rtcfifo,rtcmem,rtctime,sntp,tmr,uart,wifi
Not sure if this should be an answer or a comment. May be a bit long for a comment though.
So, the question is "Is this a known constraint?" and the short but unsatisfactory answer is "no". Can't leave it like that...
Is the code excerpt enough for you to conclude the reset must occur due to something within those few lines? I doubt it.
What you seem to be doing is a simple "global" increment of each GPIO 'down' with some debounce logic. However, I don't see any debounce, what am I missing? You get the time into the global lastTrig but you don't do anything with it. Just for debouncing you won't need rtctime IMO but I doubt it's got anything to do with the problem.
I have a gist of a tmr.delay-based debounce as well as one with tmr.now that is more like a throttle. You could use the first like so:
GPIO14 = 5
spin
function down()
spin = spin + 1
tmr.delay(50) -- time delay for switch debounce
gpio.trig(GPIO14, "up", up) -- change trigger on falling edge
end
function up()
tmr.delay(50)
gpio.trig(GPIO14, "down", down) -- trigger on rising edge
end
gpio.mode(GPIO14, gpio.INT) -- gpio.FLOAT by default
gpio.trig(GPIO14, "down", down)
I also suggest running this against the dev branch because you said it be related to network I/O during interrupts.
I have nearly the same problem.
Running ESP8266Webserver, using GPIO14 Interrupt, with too fast Impulses as input ,
the system stopps recording the interrupts.
Please see here for more details.
http://www.esp8266.com/viewtopic.php?f=28&t=9702
I'm using ARDUINO IDE 1.69 but the Problem seems to be the same.
I used an ESP8266-07 as generator & counter (without Webserver)
to generate the Pulses, wired to my ESP8266-Watersystem.
The generator works very well, with much more than 240 puls / sec,
generating and counting on the same ESP.
But the ESP-Watersystem, stops recording interrupts here at impuls > 50/ second:
/*************************************************/
/* ISR Water pulse counter */
/*************************************************/
/**
* Invoked by interrupt14 once per rotation of the hall-effect sensor. Interrupt
* handlers should be kept as small as possible so they return quickly.
*/
void ICACHE_RAM_ATTR pulseCounter()
{
// Increment the pulse Counter
cli();
G_pulseCount++;
Serial.println ( "!" );
sei();
}
The serial output is here only for showing whats happening.
It shows the correct counted Impuls, until the webserver interacts with the network.
Than is seams the Interrupt is blocked.(no serial output from here)
By stressing the System, when I several times refresh the Website in an short time,
the interrupt counting starts for an short time, but it stops short time again.
The problem is anywhere along Interrupt handling and Webservices.
I hope I could help to find this issues.
Interessted in getting some solutions.
Who can help?
Thanks from Mickbaer
Berlin Germany
Email: michael.lorenz#web.de
looking for a little help.
I'm familiar with PIC Microcontrollers but have never used Atmel.
I'm required to use an ATMEGA128 for a project at work so I've been playing around in Atmel Studio 6 the last few days.
I'm having an issue however, I can't even get an LED to blink.
I'm using the STK500 and STK501 Dev boards and the JTAGICE_MKII USB debugger/programmer.
The ATMEGA128 chip is a TQFP package that's in the socket on the STK501 board.
I'm able to program/read the chip no problems, and my code builds without error (except for when I try to use the delay functions used in the delay.h library - but that's another issue).
For now I'm just concerned with getting the IO working. I have a jumper from 2 bits of PORTD connecting to 2 of the LEDs on the STK500 board.
All I'm doing in my code is setting the PORT direction with the DDRx ports and then setting all the PORTD pins to 0. The LEDs remain turned on.
When I'm in debugging mode and I have the watch window open, I can break the code and the watch windows shows me that the PORTD bits are indeed all 0's, but the LEDs remain on.
So far, I hate Atmel. :)
Any ideas?
Thanks
Have you tried setting them to logic 1? It is common for LED circuits to connect the LED to Vcc via a current-limiting resistor, which means the output port has to be 0 to turn on the LED.
If you set it to 1 and the LED goes off, then that'll tell you it's an "active low" signal and you can reverse your logic accordingly.
Have you read the STK500's doc? It is likely, that the LEDs are driven active low.
There are two steps to follow. First you set the "direction" of the pins, because they can be used as input or output. To make the D register pins output pins:
DDRD = 0xFF;
This will set all pins on the D register as output pins. Do this first. Then code like:
PORTD != 0x01;
will set the D0 pin high. And code like
PORTD ^= 0x01;
will toggle the pin.
See this tutorial for a little more info or visit in with this community. The Atmel community is vibrant and helpful.