i'm trying to port snd_bcm2835 to mainline kernel(mainly because the rpi official kernel doesn't use device tree).
now the vcio, vchiq, snd_bcm2835 can all be insmod into the kernel, but there's still no valid device for audio playback.
the module_init function of snd_bcm2835 module is bcm2835_alsa_device_init(), it's main job is(a simplify version):
static int bcm2835_alsa_device_init(void)
{
platform_driver_register(&bcm2835_alsa0_driver);
platform_driver_register(&bcm2835_alsa1_driver);
//...repeat for 8 times
}
this bcm2835_alsa_device_init function is called when i insmod snd_bcm2835, it can be run without error.
and the struct bcm2835_alsa0_driver, bcm2835_alsa1_driver look like:
static struct platform_driver bcm2835_alsa0_driver = {
.probe = snd_bcm2835_alsa_probe,
.remove = snd_bcm2835_alsa_remove,
//...
}
the .probe function snd_bcm2835_alsa_probe is the main workhorse, but it was not been called.
so the question is when will this snd_bcm2835_alsa_probe been called?
I have ported 4.0 on raspberry pi using the following steps given by elinux, and i was succesfull . So you can also give a try:Raspberry pi Upstream
Related
I have a main binary and an app binary. Main binary is compiled with FreeRTOS and has access to HAL layer and thus uart.
App binary is loaded at runtime. Now from App binary I need to call a uart_print function of main binary to log the message from uart. Apart from this also I need to call other function of main binary from app binary.
I searched on web and found How to write dynamic loader for bare-metal arm-application which suggest implementing jump tables.
I have the following implementation:
jumptbl.h
typedef struct _MyAPI
{
void (*jumptbl_msg)(const char *msg);
} MyAPI;
In main binary I have instantiate the structure:
void PrintMsg(const char* msg)
{
HAL_UART_Transmit(&huart3, (uint8_t*)'\n', 1,10);
}
__attribute__ ((section (".jumptbl"))) MyAPI main_API =
{
&PrintMsg,
};
In linker script I create a section to be placed at address :0x20001F00
.jumptbl_block 0x2001F000:
{
KEEP(*(.jumptbl))
} > RAM
And then from app binary I call the PrintMsg function.
MyAPI *pAPI = (MyAPI*)(0x2001F000);
pAPI->jumptbl_msg("hello world");
But my program hardfaults when the jump function is called.
Also, I tried another approach. I got the address of PrintMsg using arm-none-eabi-nm and directly calling it, but again the program hard faulted.
typedef void (*t_funcPtr)(const char *);
t_funcPtr MyFunc = (t_funcPtr)0x08001af4;
MyFunc("hello world");
Please can you suggest how can I call function of one binary in section sec_x loaded at address x from another binary.
I have two kernel modules where first module had one function exported and second module uses this function to read spi data. sample program is given below
Module-1:
int spi_fun(uint8_t *tx_buf, uint8_t *rx_buf,int len)
{
spi_sync_txrx(tx_buf,rx_buf,len);
}
Module-2:
void dummy_fun()
{
uint8_t tx[4]={0};
uint8_t rx[4]={0};
spi_fun(tx,rx,4);
}
the above mentioned scenario is working fine. If I declare a local rx buffer(spi_data[4]) inside spi_fun(), and use memcpy to copy spi_data contents to the rx_buf, kernel is crashing with error as given below
New Module-2 fun:
Module-1:
int spi_fun(uint8_t *tx_buf, uint8_t *rx_buf,int len)
{
uint8_t spi_data[4];
spi_sync_txrx(tx_buf,spi_data,len);
memcpy(rx_buf, spi_data, len); //here error
}
Kernel Error:
Internal error: Accessing user space memory outside uaccess.h
routines: 96000045 [#1] PREEMPT SMP
I have used copy_from_user/copy_to_user functions, but i was getting target buffer as zeroes.
Does anyone experienced this issue???
I have some unexpected reboot on a embedded device. I am currently able to detect a hardware watchdog issue thanks to an ioctl call. Now I would like be able to detect if a kernel panic was the reason for a reboot. I find some articles concerning crashkernel and crashdump but I was not able to make it work properly. And I dont want to store the kernel panic log. Just be able to know if kernel panic happens.
My current idea was to write in a reserved space on mmc. I am currently using a reserved space to handle a double distribution system. It is a good idea ? Is it possible to write in mmc during a kernel panic ? I am not sure but its seems that I can use kind of kernel panic hook to run routine on this event.
There is no standard way to be able to check that kernel panic happened on boot ?
I was able to detect and debug kernel panic thanks to the comment from #0andriy How to detect a kernel panic after reboot
Enable ramoops in kernel defconfig :
+CONFIG_PSTORE=y
+CONFIG_PSTORE_ZLIB_COMPRESS=y
+CONFIG_PSTORE_CONSOLE=y
+CONFIG_PSTORE_RAM=y
Add code in your kernel board init to declare the ramoops memory space, you
can also use the device tree or even use a parameter in kernel procline
This is an example using the code method, in my usecase it was in
arch/arm/mach-imx/mach-imx6ul.c
--- a/arch/arm/mach-imx/mach-imx6ul.c
+++ b/arch/arm/mach-imx/mach-imx6ul.c
## -21,6 +21,24 ##
#include "cpuidle.h"
#include "hardware.h"
+#include <linux/pstore_ram.h>
+#include <linux/memblock.h>
+
+static struct ramoops_platform_data ramoops_data = {
+ .mem_address = 0xXXXXXXXX, // Depending of the hardware
+ .mem_size = 0x00005000, // 5 Mb
+ .record_size = 0x00002000, // 1 Mb
+ .dump_oops = 1,
+};
+
+static struct platform_device ramoops_dev = {
+ .name = "ramoops",
+ .dev = {
+ .platform_data = &ramoops_data,
+ },
+};
+
+
static void __init imx6ul_enet_clk_init(void)
{
struct regmap *gpr;
## -170,6 +188,14 ## static inline void imx6ul_enet_init(void)
static void __init imx6ul_init_machine(void)
{
struct device *parent;
+ int ret;
+
+ ret = platform_device_register(&ramoops_dev);
+ if (ret) {
+ printk(KERN_ERR "unable to register platform device\n");
+ return;
+ }
+ memblock_reserve(ramoops_data.mem_address, ramoops_data.mem_size);
parent = imx_soc_device_init();
if (parent == NULL)
Then on boot I just have to check the content of ramoops to check if there is some kernel panic log available. I can mount the ramoops memory space with :
mount -t pstore -o kmsg_bytes=1000 - /sys/fs/pstore
Here's how Windows handles it:
do not use drivers any more
write to disk using BIOS routines (or something low level as this)
write the kernel dump into the page file (the only known place which is contiguous and known that we can write to without damaging anything)
on next boot, check if the page file contains a crash dump signature
You might be able to apply this concept to Linux, e.g. write to the swap partition and check the contents of the swap partition at next startup.
How can I configure Keil uVision5 to redirect printf output from STM32F4xx out through MCU's USB interface? Then, USB will connect to a Windows computer, virtual port driver, and a terminal program.
I cannot find an example uVision5 project that configures printf to output through the STM32F4xx MCU's USB interface.
The USB of the STM32F4xx MCU has to implement the USB CDC as device class or interface class (https://en.wikipedia.org/wiki/USB_communications_device_class) and in host mode (USB OTG) in its firmware. On the PC's USB has to be created a virtual COM port (driver) to process the RS232 protocol that the STM32F4 sends over the USB CDC (in host mode). When the CDC firmware on the STM32F4 is working correctly, on linux the STM32F4 appears i.e. as /dev/ttyACM0 and this can be accessed with standard RS232 terminal programs.
basics -> http://www.keil.com/support/man/docs/rlarm/rlarm_usb_create_cdc_acm.htm
Here is a basic example how to send serial data over USB CDC (that on pc's USB appears as a Virtual COM port i.e. /dev/ttyACM0): http://visualgdb.com/tutorials/arm/stm32/usb/
See also this http://stm32f4-discovery.net/2014/08/library-24-virtual-com-port-vcp-stm32f4xx/
Follow or adapt the tutorial above to linux (http://visualgdb.com/tutorials/arm/stm32/usb/).
To redirect printf() to USB CDC override the standard I/O routines like in the following. The ARM version of printf() invokes these routines then, see this https://mcuoneclipse.com/2014/07/11/printf-and-scanf-with-gnu-arm-libraries/ (the ARM version of printf() is very different from the x86/x64 version of printf()):
#include<sys/stat.h>
extern"C"
{
int _fstat (int fd, struct stat *pStat)
{
pStat->st_mode = S_IFCHR;
return 0;
}
int _close(int)
{
return -1;
}
int _write (int fd, char *pBuffer, int size)
{
return VCP_write(pBuffer, size);
}
int _isatty (int fd)
{
return 1;
}
int _lseek(int, int, int)
{
return -1;
}
int _read (int fd, char *pBuffer, int size)
{
for (;;)
{
int done = VCP_read(pBuffer, size);
if (done)
return done;
}
}
}
Or use the ARM semihosting interface (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0471c/Bgbjhiea.html). It will provide the functionality automatically to redirect printf() to USB CDC
More information:
http://www.keil.com/forum/60565/ (usbd_STM32F4xx_FS.c)
http://www.beyondlogic.org/usbnutshell/usb1.shtml
This is an example how to implement a USB-RS232 adapter: http://www.wolinlabs.com/blog/stm32f4.virtual.com.port.html
The git also contains many interesting files git clone https://github.com/rowol/stm32_discovery_arm_gcc
I use the following module code to hooks syscall, (code credited to someone else, e.g., Linux Kernel: System call hooking example).
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/unistd.h>
#include <asm/semaphore.h>
#include <asm/cacheflush.h>
void **sys_call_table;
asmlinkage int (*original_call) (const char*, int, int);
asmlinkage int our_sys_open(const char* file, int flags, int mode)
{
printk(KERN_ALERT "A file was opened\n");
return original_call(file, flags, mode);
}
int set_page_rw(long unsigned int _addr)
{
struct page *pg;
pgprot_t prot;
pg = virt_to_page(_addr);
prot.pgprot = VM_READ | VM_WRITE;
return change_page_attr(pg, 1, prot);
}
int init_module()
{
// sys_call_table address in System.map
sys_call_table = (void*)0xffffffff804a1ba0;
original_call = sys_call_table[1024];
set_page_rw(sys_call_table);
sys_call_table[1024] = our_sys_open;
return 0;
}
void cleanup_module()
{
// Restore the original call
sys_call_table[1024] = original_call;
}
When insmod the compiled .ko file, terminal throws "Killed". When looking into 'cat /proc/modules' file, I get the Loading status.
my_module 10512 1 - Loading 0xffffffff882e7000 (P)
As expected, I can not rmmod this module, as it complains its in use. The system is rebooted to get a clean-slate status.
Later on, after commenting two code lines in the above source sys_call_table[1024] = our_sys_open; and sys_call_table[1024] = original_call;, it can insmod successfully. More interestingly, when uncommenting these two lines (change back to the original code), the compiled module can be insmod successfully. I dont quite understand why this happens? And is there any way to successfully compile the code and insmod it directly?
I did all this on Redhat with linux kernel 2.6.24.6.
I think you should take a look to the kprobes API, which is well documented in Documentation/krpobes.txt. It gives you the ability to install handler on every address (e.g. syscall entry) so that you can do what you want. Added bonus is that your code would be more portable.
If you're only interested in tracing those syscalls you can use the audit subsystem, coding your own userland daemon which will be able to receive events on a NETLINK socket from the audit kthread. libaudit provides a simple API to register/read events.
If you do have a good reason with not using kprobes/audit, I would suggest that you check that the value you are trying to write to is not above the page that you set writable. A quick calculation shows that:
offset_in_sys_call_table * sizeof(*sys_call_table) = 1024 * 8 = 8192
which is two pages after the one you set writable if you are using 4K pages.