How NVIC function working NVIC_EnableIRQ(CAN1_RX0_IRQn); - protocols

so my friend asked me to write my own implementation for above function NVIC_Enable_IRQ(CAN1_RX0_IRQn); to enable can reception interrupt.
initially i thought its impossible to right such implementation ..
could anybody please explain me like the register associated with NVIC where i directly go and change the required value ,so that there is no need of implementation of above function and CAN reception interrupt is enabled.
this line NVIC_EnableIRQ(CAN1_RX0_IRQn); i copied from example code given in stm32f example code of CAN

Everything that starts with NVIC_ is part of the CMSIS library supplied by ARM to set up the ARM core (which is independent of the MCU manufacturer). You don't really want to mess with them, so you'd better use them.
In the CMSIS core_cm4.h (for a cortex M4), you can find:
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
{
NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
Now, if you don't want to call NVIC_EnableIRQ or if you don't want to use the CMSIS, well good luck, you need to read the ARM core documentation to check which addresses you need to modify. The ARM core documentation can be found on the ARM or Keil website. For example, you might find those links useful for the Cortex M4:
https://www.arm.com/products/processors/cortex-m/cortex-m4-processor.php
http://www.keil.com/dd/docs/datashts/arm/cortex_m4/r0p1/dui0553a_cortex_m4_dgug.pdf

Related

What is the Device parameter in Mix_OpenAudioDevice ( SDL2 )

While I know how to use MIX_OpenAudio.... I wanted to know the use of MIX_OpenAudioDevice function
It takes several arguments... Device name is one of them
So, I want to know that how can we know what the device name is
It says we can use a function i.e. SDL_GetAudioDeviceName()
But how would we know which audio device to choose on every system....
Or is this function only for working with specific audio systems such as realtek or something?
So from how I understand it, MIX_OpenAudio() is already using MIX_OpenAudioDevice(), just using a NULL value for the device parameter (which then defaults to whatever the system uses for sound). The only reason you would need to specify an actual device in that function is if you are expecting your audio data to be in a specific format. Therefore you should already know what it is.
From the docs: (link)
If you aren't particularly concerned with the specifics of the audio device, and your data isn't in a specific format, the values you use here can just be reasonable defaults.
This function allows you to select specific audio hardware on the system with the device parameter. If you specify NULL, SDL_mixer will choose the best default it can on your behalf (which, in many cases, is exactly what you want anyhow). SDL_mixer does not offer a mechanism to determine device names to open, but you can use SDL_GetNumAudioDevices() to get a count of available devices and then SDL_GetAudioDeviceName() in a loop to obtain a list. If you do this, be sure to call SDL_Init(SDL_INIT_AUDIO) first to initialize SDL's audio system!
As the doc says there, SDL_GetNumAudioDevices() will allow you to loop through SDL_GetAudioDeviceName() to see if it exists on the machine.
This would allow you more control over your audio and can save CPU time from converting the data to the exact device. You also must have that device already opened as well.
Also a link to the SDL2 docs.
Hope this helps explain that function.

How can I access or enumerate available LEDs from kernel code (BeagleBone Black)?

I am trying to write a custom syscall handler that manipulates the LEDs on a BeagleBone Black board. I have gone through the kernel LED API (include/leds.h), but I am unable to find anything that'd give me a handle to the available LED devices or some other mechanism to manipulate (on/off/toggle) them. Most of the functions seem to require a led_classdev object, but I can't find a way of getting one.
I can do this from userspace using the /sys/class/leds/... interface. But I want to do something similar from kernel space. I am open to hard-coding any device names specific to BeagleBone Black as portability is not an issue.
I figured out a way to access/control the LEDs from kernel space - by creating a custom LED trigger. It doesn't give a way to enumerate available devices, and it requires the custom trigger to be assigned for an LED from user-space by writing to /sys/class/leds/foo/trigger. But it lets you manipulate the LEDs from kernel code once the trigger is assigned.
struct led_trigger *trigger;
...
led_trigger_register_simple("myled", &trigger); //create and register the trigger
...
//assign the trigger "myled" to the desired LED(s) from user-space
//by writing to the corresponding trigger files in /sys/class/leds/foo/
...
led_trigger_event(trigger, LED_FULL); //turn-on the LED(s) connected to the trigger
led_trigger_event(trigger, LED_OFF); //turn-off
The creation and registering of trigger can be done in a module init, for example. Also, if one needs to manipulate multiple LEDs independently, then as far as I can see, one needs to create separate triggers for each LED.

Is there a way to have a ioctl() with new(customized) command

I am working on a testing tool for nvme-cli(written in c and can run on linux).
For SSD validation purpose, i was actually looking for a custom command(For e.g. I/O command, write and then read the same and finally compare if both the data are same)
In user space i need to invoke minimum of 2 ioclt() one with write command(nvme_cmd_write) and another with read command(nvme_cmd_read) and compare both the buffer contents.
Issue is actually when i wanted to send this command in parallel. At block level (using ioclt())we were not able to put this command in different I/O submission queues.
so can we have a custom command (nvme_cmd_write_compare) sent from ioclt() and have a new module at driver level for handling this new command.
Since I am new to this nvme/ioctl(), if there is any mistakes please correct me.
I wanted to know if we can implement this.

How can I determine what MTD flash device is installed (e.g. get the ID or serial number)?

Using uClinux we have one of two flash devices installed, a 1GB flash or a 2GB flash.
The only way I can think of solving this is to somehow get the device ID - which is down the in the device driver code, for me that is in:
drivers/mtd/devices/m25p80.c
I have been using the command mtdinfo (which comes from mtdutils binaries, derived from mtdinfo.c/h). There is various information stored in here about the flash partitions including flash type 'nor' eraseblock size '65536', etc. But nothing that I can identify the chip with.
Its not very clear to me how I can get information from "driver-land" into "user-land". I am looking at trying to extend the mtdinfo command to print more information but there are many layers...
What is the best way to achieve this?
At the moment, I have found no easy way to do this without code changes. However I have found an easy code change (probably a bit of a hack) that allows me to get the information I need:
In the relevant file (in my case drivers/mtd/devices/m25p80.c) you can call one of the following:
dev_err("...");
dev_alert("...");
dev_warn("...");
dev_notice("...");
_dev_info("...");
Which are defined in include/Linux/device.h, so they are part of the Linux driver interface so you can use them from any driver.
I found that the dev_err() and devalert() both get printed out "on screen" during run time. However all of these device messages can be found in /var/log/messages. Since I added messages in the format: dev_notice("JEDEC id %06x\n", jedecid);, I could find the device ID with the following command:
cat /var/log/messages | grep -i jedec
Obviously using dev_err() ordev_alert() is not quite right! - but dev_notice() or even _dev_info() seem more appropriate.
Not yet marking this as the answer since it requires code changes - still hoping for a better solution if anyone knows of one...
Update
Although the above "solution" works, its a bit crappy - certainly will do the job and good enough for mucking around. But I decided that if I am making code changes I may as well do it properly. So I have now implemented changes to add an interface in sysfs such that you can get the flash id with the following command:
cat /sys/class/m25p80/m25p80_dev0/device_id
The main function calls required for this are (in this order):
alloc_chrdev_region(...)
class_create(...)
device_create(...)
sysfs_create_group(...)
This should give enough of a hint for anyone wanting to do the same, though I can expand on that answer if anyone wants it.

How to find TLS segments of the current thread on linux amd64?

I'm looking for a way to find out the memory addresses of TLS segments for the current thread on linux, amd64. Bonus point for a solution that works on OSX.
Looked into various language runtime or GC (like boehm), but couldn't go through the multiple layer of abstractions to support all kind of systems so far. Any help appreciated.
Did you have a look at the solution Martin and I came up with in druntime?
What we do there boils down to scanning the segments in the corresponding dl_phdr_info (obtained by looking for the correct one using dl_iterate_phdr) for the segment with type PT_TLS, and storing its module id and size.
You can then get the start of the address range on the current thread by calling __tls_get_addr for offset 0 and the module id (there is an offset on some archs), and the end by simply adding the size you determined to that. If you do not need to support shared libraries, you can also simply use fs/gs on x86 for that (might be required if you want to link a static executable).
This works for Linux and FreeBSD (and probably other ELF platforms), but not OS X. There, the best I could come up with so far is this:
void _d_dyld_getTLSRange(void* arbitraryTLSSymbol, void** start, size_t* size) {
dyld_enumerate_tlv_storage(
^(enum dyld_tlv_states state, const dyld_tlv_info *info) {
assert(state == dyld_tlv_state_allocated);
if (info->tlv_addr <= arbitraryTLSSymbol &&
arbitraryTLSSymbol < (info->tlv_addr + info->tlv_size)
) {
// Found the range we are looking for.
*start = info->tlv_addr;
*size = info->tlv_size;
}
}
);
}
The naive implementation currently used in LDC's druntime does not quite handle shared libraries, though, and dyld_enumerate_tlv_storage is from dyld_priv.h, which might or might not be a problem for App Store publishing.
On Linux, the thread-specific segment is set up via arch_prtcl(ARCH_SET_FS, <addr>) call. You can find out what it was set to in the current thread via arch_prctl(ARCH_GET_FS, ...).
Bonus point for a solution that works on OSX.
OSX is a completely different OS, and uses completely different mechanism for its TLS support.

Resources