What's this linux structure - linux

#define GPIO_CHIP(_bank) { \
.irq_base = IRQ_GPIO_BASE_ ## _bank, \
.gpio_chip = { \
.label = "Bank " # _bank, \
.owner = THIS_MODULE, \
.set = gpio_set_value, \
.get = gpio_get_value, \
.direction_output =gpio_direction_output, \
.direction_input = gpio_direction_input, \
.base = GPIO_BASE_ ## _bank, \
.ngpio =GPIO_NUM_ ## _bank, \
}, \
}
What's this define with .label and .set and others?
static void gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
{
uint32_t __iomem *reg = CHIP_TO_REG(chip, REG_GPIO_DATA_SET);
reg += !value;
writel(BIT(gpio), reg);
}
This function with writel, __iomen, BIT() , where are they referenced from in Linux?

GPIO_CHIP is used to initialize a struct for a bank of GPIO (General Purpose I/O). If you have
struct s {
int a, b, c;
char * d;
}
then you can initialize a variable like
struct s example = { .a = 1, .b = 2, .c = 3, .d = "Hello!" };
You could also do it like
struct s example = { 1, 2, 3, "Hello!" };
but in that case you need to keep track of the order of the members of the struct, it isn't obvious at a glance what 1, 2, etc. actually being used for, and it can get out of sync easily.
If you need to initialize a lot of variables like this you can use a #define which is just the initializer, like
#define S_INIT(num) { .a = num, .b = 2, .c = 3 }
struct s example = S_INIT(0);
struct s examples[] = { S_INIT(1), S_INIT(2), S_INIT(3) };
GPIO_CHIP sets the function pointer .gpio_chip.set in the structure to point to gpio_set_value, so any call to that function is likely through that function pointer.
Consult the kernel documentation for the GPIO driver interface for details.

Related

how can i read some struct param in attribute section "test"?

test.h
struct test_desc {
const char *name;
}
#define PFM_TEST(a,name) struct test_desc a \
__attribute__((section("test"))) = {name}
test.c
PFM_TEST(name1,abc);
PFM_TEST(name2,dec);
main.c
#pragma section = "test"
void main(void)
{
struct struct test_desc *start,*stop;
start = (struct test_desc *)__section_begin("test");
stop = (struct test_desc *)__section_end("test");
printf("start->name = %s\n",start->name);
}
test.icf
define symbol __ICFEDIT_region_TEST_start__ = (0x10080000);
define symbol __ICFEDIT_region_TEST_end__ = (0x100DFFFF);
define region TEST_region = mem:[from __ICFEDIT_region_TEST_start__ to __ICFEDIT_region_TEST_end__];
keep { section test};
place at start of TEST_region {readwrite,section test};
actual result
hard fault patch...
expect result
start->name = abc
i can read the test section start address and stop address,i think i could cast them as test_desc type. but the actual result is error.
i think maybe i can't put the section into the .data,how can i do that?
Finally, i set the section next to the .data section.like this
define block .ram_image2.data with fixed order{ section .data*,
section DATA,
section test*,
section .iar.init_table,
section __DLIB_PERTHREAD,
block CPP_INIT,
};
expect result i can get,and the param is not the const type.
modify
before
#define PFM_TEST(a,name) struct test_desc a \
__attribute__((section("test"))) = {name}
later
#define PFM_TEST(a,name) const struct test_desc a \
__attribute__((section("test"))) = {name}
it could get my expect result,but i don't want the struct to be const.
I think i should take the section into the right memory like .data.but i don't know how can i do that.

How are the steps to access GPIOs in linux kernel modules?

I am struggling to find out, what steps are necessary to access a gpio-pin from a linux kernel module.
Maybe someone can explain it to me by a simple example. I like to use pin 4(input) and 33(output). My steps so far:
1.) Device Tree(dts): I leave the dts file untouched - Do I need to setup the pin 4 and 33 via pin control?
2.) kernel module: some pseudo code
gpio_is_valid(4)
gpio_request_one(4, GPIOF_DIR_IN | GPIOF_EXPORT_DIR_FIXED , "myPin4")
gpio_export(4, false)
gpio_get_value(4)
gpio_is_valid(33)
gpio_request_one(33, GPIOF_DIR_OUT | GPIOF_INIT_LOW | GPIOF_OPEN_SOURCE | GPIOF_EXPORT_DIR_FIXED , "myPin33")
gpio_export(33, false)
gpio_set_value(33, 1)
How to do it in a proper way?
I would suggest the combination of an own device tree file + a platform driver + character driver
0.) RTF
check how device trees(dts) are working
check how a platform device works
check how a character device works
gain some knowledge about gpios and dts
#gpio mappings
#subsystems using gpios
#Specifying GPIO information for devices
Read the informations provided by your SOC manufacturer.
The state-of-the-art way to access the gpios is via struct gpio_desc variables. They are created form the device tree.
1.) approach
To toggle a pin under linux you need to make shure, that 3 units are working togehter.
The pin-controller(pinctrl) defines how the output is driven. Open source, pull up etc.
The pin-multiplexer(pinmux) defines different functions for the pin.
The gpio-controller(gpioctrl) translates the gpio number. p.E.: 44 -> GPIO A 11
These components are implemented by the SOC manufacturer. For each platform there are differences. An example for the SAMA5D35xxx follows.
#the device tree
Define the pin controller
pinctrl#fffff200 {
pinctrl_myPins: myPins {
atmel,pins = <AT91_PIOA 2 AT91_PERIPH_GPIO AT91_PINCTRL_NONE // pin 1
AT91_PIOD 19 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>; // pin 2
};
};
Create a node witch is linked to the own platform device:
myPins {
compatible = "myPlatformDevice";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_myPins>;
pin1 = <&pioA 2 GPIO_ACTIVE_HIGH>;
pin2 = <&pioD 19 GPIO_ACTIVE_HIGH>;
};
#create platform + char driver (pseudo code):
// ----------------------
// kernel message support(via dmesg)
// ----------------------
#define KMSG_DEBUG(fmt,args...) printk(KERN_DEBUG "myDrv" ": "fmt"\n", ##args)
#define KMSG_PERR(fmt,args...) printk(KERN_ERR "myDrv" ": "fmt"\n", ##args)
#define KMSG_PINFO(fmt,args...) printk(KERN_INFO "myDrv" ": "fmt"\n", ##args)
// ----------------------
// trace support via defining dMyDrvTrace
// ----------------------
#ifndef dMyDrvTrace
#define TRACE(...)
#else
#define TRACE(fmt,args...) printk(KERN_INFO "myDrv" ": [%s] "fmt"\n", __FUNCTION__, ##args)
#endif
typedef struct SMyDrvDrvData {
struct platform_device *pdev; //!< next device
// here goes the local/private data
int gpiod_pin1;
int gpiod_pin2;
u32 pin1;
u32 pin2;
} TMyDrvDrvData;
static struct dentry * gmyPlattformDrvDebugfsRootDir; //!< root dir at debugfs
static int myPlattformDrv_probe(struct platform_device *pdev);
static int myPlattformDrv_remove(struct platform_device *pdev);
#if defined(CONFIG_OF)
//! filter for the device tree class
static struct of_device_id gMyPlattformDrvdtsFilter[] = {
{.compatible = "myPlatformDevice"},
{}
};
MODULE_DEVICE_TABLE(of, gMyPlattformDrvdtsFilter);
#else
#define gmyPlattformDrvdtsFilter (NULL)
#endif
static struct platform_device *MyPlattformDrv_devs[] = {
};
static struct platform_driver myPlattformDrv_driver = {
.driver = {
.name = dMyPlattformDrvdriver,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(gMyPlattformDrvdtsFilter),
},
.probe = myPlattformDrv_probe,
.remove = myPlattformDrv_remove,
};
// char device
static dev_t gMyCharDev;
static struct class *gMyCharDevClass;
static struct cdev gMyCharDev_cdev;
static int dev_open (struct inode *, struct file *);
static int dev_release (struct inode *, struct file *);
static ssize_t dev_read (struct file *, char *, size_t, loff_t *);
static ssize_t dev_write (struct file *, const char *, size_t, loff_t *);
static const struct file_operations gMyCharDevOps =
{
.read = dev_read,
.open = dev_open,
.write = dev_write,
.release = dev_release
};
//! looks up for the gpio name and request it
static int get_gpio(struct platform_device *pdev, const char * name, int * pGPIOnum)
{
int n,i;
int r;
struct device_node * pDN;
TRACE("look at %s for %s ...", pdev->name, name);
// reset return value
*pGPIOnum = 0;
// parse device tree
// get device tree entries associated with the device
pDN = of_find_node_by_name(NULL, pdev->name);
// parse pins
n = of_gpio_named_count(pDN, name);
if (n <= 0) {
TRACE("no gpios found");
return -1;
}
for (i = 0; i < n; i++) {
// get pin number
*pGPIOnum = of_get_named_gpio(pDN,name, i);
if (*pGPIOnum == -EPROBE_DEFER) {
return r;
}
// check if pin number is valid
if (gpio_is_valid(*pGPIOnum)) {
// yes
// request pin
r = devm_gpio_request(&pdev->dev, *pGPIOnum, name);
if (r) {
return r;
} else {
r = gpio_direction_output(*pGPIOnum, 0);
}
if (r) return r;
}
}
}
return 0;
}
//! probes the platform driver
static int myPlattformDrv_probe(struct platform_device *pdev)
{
struct TMyDrvDrvData *priv;
int i,j,r,gpioNum, ret;
KMSG_PINFO("probe my driver ...");
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
KMSG_PERR("Failed to allocate memory for the private data structure");
return -ENOMEM;
}
priv->pdev = pdev;
platform_set_drvdata(pdev, priv);
TRACE("setup gpios ...");
r = get_gpio(pdev, "pin1", &gpioNum);
if (r) {
KMSG_PERR("Failed to find gpio \"pin1\" in device tree");
}
// save number
priv->gpiod_pin1 = gpioNum;
// create "pin1" debugfs entry
debugfs_create_u32("pin1", S_IRUGO, gmyPlattformDrvDebugfsRootDir, &priv->Pin1);
r = get_gpio(pdev, "pin2", &gpioNum);
if (r) {
KMSG_PERR("Failed to find gpio \"pin2\" in device tree");
}
// save number
priv->gpiod_pin2 = gpioNum;
// create "pin2" debugfs entry
debugfs_create_u32("pin1", S_IRUGO, gmyPlattformDrvDebugfsRootDir, &priv->Pin2);
// create device class
TRACE("create myCharDev char device class");
// create char dev region
ret = alloc_chrdev_region(&gMyCharDev, 0, 1, "myCharDev");
if( ret < 0) {
KMSG_PERR("alloc_chrdev_region error %i", ret);
goto error;
}
// create device class
if((gMyCharDevClass = class_create(THIS_MODULE, dSEK4DevClass)) == NULL)
{
KMSG_PERR("class_create error");
goto error_classCreate;
}
if(NULL == device_create(gMyCharDevClass, NULL, gMyCharDev, NULL, "myCharDev"))
{
KMSG_PERR("device_create error");
goto error_deviceCreate;
}
cdev_init(&gMyCharDev_cdev, &gMyCharDevOps);
ret = cdev_add(&gMyCharDev_cdev, gMyCharDev, 1);
if(-1 == ret) {
KMSG_PERR("cdev_add error %i", ret);
goto error_device_add;
return -1;
}
TRACE("added myCharDev char device");
return 0;
// error handling block
error_std:
error_device_add:
device_destroy(gMyCharDevClass, gMyCharDev);
error_deviceCreate:
class_destroy(gMyCharDevClass);
error_classCreate:
unregister_chrdev_region(gMyCharDev, 1);
error:
return -1;
}

Is there a Lua string replace() function for faster replacements than gsub()?

I see a list of Lua string functions and I see the .gsub(), for global search and replace: http://www.gammon.com.au/scripts/doc.php?general=lua_string
All lua string functions :
static const luaL_Reg strlib[] = {
{"byte", str_byte},
{"char", str_char},
{"dump", str_dump},
{"find", str_find},
{"format", str_format},
{"gfind", gfind_nodef},
{"gmatch", gmatch},
{"gsub", str_gsub},
{"len", str_len},
{"lower", str_lower},
{"match", str_match},
{"rep", str_rep},
{"reverse", str_reverse},
{"sub", str_sub},
{"upper", str_upper},
{NULL, NULL}
};
Why is there no simple, fast, litteral (non-regex) string replace function?
Is .gsub() so efficient that there is no benefit?
I found this written in 2006 but it does not seem like it's included: http://lua-users.org/wiki/StringReplace
This is likely because gsub is capable of doing exactly what a replace function would do, and Lua's design goals include that of a small, generally uncomplicated standard library. There's no need for a redundancy like this to be baked right into the language.
As an outside example, the Ruby programming language provides both String#gsub and String#replace in its standard library. Ruby is a much, much larger language out of the box because of decisions like this.
However, Lua prides itself on being a very easy language to extend. The link you've shown shows how to bake the function into the standard library when compiling Lua as a whole. You could also piece it together to create a module.
Quickly patching together the parts we need results in (note we need the lmemfind function from lstrlib.c):
#include <lua.h>
#include <lauxlib.h>
#include <string.h>
static const char *lmemfind
(const char *s1, size_t l1, const char *s2, size_t l2) {
if (l2 == 0)
return s1; /* empty strings are everywhere */
else if (l2 > l1)
return NULL; /* avoids a negative 'l1' */
const char *init; /* to search for a '*s2' inside 's1' */
l2--; /* 1st char will be checked by 'memchr' */
l1 = l1-l2; /* 's2' cannot be found after that */
while (l1 > 0 && (init = (const char *) memchr(s1, *s2, l1)) != NULL) {
init++; /* 1st char is already checked */
if (memcmp(init, s2+1, l2) == 0)
return init-1;
else { /* correct 'l1' and 's1' to try again */
l1 -= init-s1;
s1 = init;
}
}
return NULL; /* not found */
}
static int str_replace(lua_State *L) {
size_t l1, l2, l3;
const char *src = luaL_checklstring(L, 1, &l1);
const char *p = luaL_checklstring(L, 2, &l2);
const char *p2 = luaL_checklstring(L, 3, &l3);
const char *s2;
int n = 0;
int init = 0;
luaL_Buffer b;
luaL_buffinit(L, &b);
while (1) {
s2 = lmemfind(src+init, l1-init, p, l2);
if (s2) {
luaL_addlstring(&b, src+init, s2-(src+init));
luaL_addlstring(&b, p2, l3);
init = init + (s2-(src+init)) + l2;
n++;
} else {
luaL_addlstring(&b, src+init, l1-init);
break;
}
}
luaL_pushresult(&b);
lua_pushnumber(L, (lua_Number) n); /* number of substitutions */
return 2;
}
int luaopen_strrep (lua_State *L) {
lua_pushcfunction(L, str_replace);
return 1;
}
We can compile this into a shared object with the proper linkage (cc -shared, cc -bundle, etc...), and load it into Lua like any other module with require.
local replace = require 'strrep'
print(replace('hello world', 'hello', 'yellow')) -- yellow world, 1.0
This answer is a formalized reconstruction of the comments above.

How to parse interleaved buffer into distinct multiple channel buffers with PortAudio

hope you can help me :)
I'm trying to get audio data from a multichannel ASIO device with PortAudio library. Everything is ok: I managed to set the default host API as ASIO and I also managed to select 4 specific channels as inputs. Then,I get an interleaved audio stream which sounds correctly but i would like to get each channel data separately.
PortAudio allows to do a non-interleaved recording, but I don't know how to write or modify my RecordCallBack and the multibuffer pointer (one buffer per channel). Sure I've tried... :(
It would be of massive help to me if someone knows how to deal with this issue.
The original RecordCallBack function is taken from a well known stereo example (slightly modified to manage 4 channles instead of 2) but it manages a single interleaved buffer:
static int recordCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
const short *rptr = (const short*)inputBuffer;
short *wptr = &data->recordedSamples[data->frameIndex * NUM_CHANNELS_I];
long framesToCalc;
long i;
int finished;
unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
(void) outputBuffer; /* Prevent unused variable warnings. */
(void) timeInfo;
(void) statusFlags;
(void) userData;
if( framesLeft < framesPerBuffer )
{
framesToCalc = framesLeft;
finished = paComplete;
}
else
{
framesToCalc = framesPerBuffer;
finished = paContinue;
}
if( inputBuffer == NULL )
{
for( i=0; i<framesToCalc; i++ )
{
*wptr++ = SAMPLE_SILENCE; /* ch1*/
if( NUM_CHANNELS_I == 4 ){
*wptr++ = SAMPLE_SILENCE;/* ch2*/
*wptr++ = SAMPLE_SILENCE;/* ch3*/
*wptr++ = SAMPLE_SILENCE;} /* ch4*/
}
}
else
{
for( i=0; i<framesToCalc; i++ )
{
*wptr++ = *rptr++; /* ch1*/
if( NUM_CHANNELS_I == 4 ){
*wptr++ = *rptr++;/* ch2*/
*wptr++ = *rptr++;/* ch3*/
*wptr++ = *rptr++;} /* ch4*/
}
}
data->frameIndex += framesToCalc;
return finished;
}
The *inputbuffer pointer is declared as:
PaStream* stream;
And the Open_Stream function is called:
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
playCallback,
&data );
Interleaved just means the bytes for each channel follow after each other as in :
aabbccddeeaabbccddeeaabbccddee (each character represents one byte)
where this input buffer contains two bytes (16 bits) per each of the 5 channels : a, b, c, d & e as it makes 3 repeats across the set of channels which equates to 3 samples per channel ... so knowing input is interleaved, it could be extracted into separate output channel buffers one per channel, but in your code you have just a single output buffer which as you say is due to the necessary callback signature ... one approach would be to write each output channel into the single output buffer separated by distinct offsets per channel so output would be
aaaaaabbbbbbccccccddddddeeeeee
then outside the callback extract out each channel also using same offset per channel
First you need to obtain size of the given output buffer, say X, number of channels, Y, and number of bytes per channel per sample, Z. So global channel offset would be
size_offset = X / (Y * Z) # assure this is an integer
# if its a fraction then error in assumptions
so when addressing output buffer both inside callback and outside we use this offset and knowledge of which channel we are on, W (values 0, 1, 2, 3, ...), and which sample K :
index_output_buffer = K + (W * size_offset) # 1st byte of sample pair
now use index_output_buffer ... then calculate follow-on index :
index_output_buffer = K + (W * size_offset) + 1 # 2nd byte of sample pair
and use it ... you could put above two commands for a given sample into a loop using Z to control number of iterations if Z were to vary but above assumes samples are two bytes
Thank's Scott for your help. The solution was right in front of my eyes and I finally didn't have to work with samples offset. I didn't give you enough information about the code, so your approach was excellent, but the code itself provides an easier way to do that:
The data is storaged in an structrue:
typedef struct
{
int frameIndex; /* Index into sample array. */
int maxFrameIndex;
short *recordedSamples;
}
paTestData;
I modified it to:
typedef struct
{
int frameIndex; /* Index into sample array. */
int maxFrameIndex;
short *recordedSamples;
short * recordedSamples2; //ch2
short * recordedSamples3; //ch3
short *recordedSamples4; //ch4
}
paTestData;
Then I just had to allocate this variables in memory and modified the recordCallback function as follows:
static int recordCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
const short *rptr = (const short*)inputBuffer;
short *wptr = &data->recordedSamples[data->frameIndex];
short *wptr2=&data->recordedSamples2[data->frameIndex];
short *wptr3=&data->recordedSamples3[data->frameIndex];
short *wptr4=&data->recordedSamples4[data->frameIndex];
long framesToCalc;
long i;
int finished;
unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
(void) outputBuffer; /* Prevent unused variable warnings. */
(void) timeInfo;
(void) statusFlags;
(void) userData;
if( framesLeft < framesPerBuffer )
{
framesToCalc = framesLeft;
finished = paComplete;
}
else
{
framesToCalc = framesPerBuffer;
finished = paContinue;
}
if( inputBuffer == NULL )
{
for( i=0; i<framesToCalc; i++ )
{
*wptr++ = SAMPLE_SILENCE; //ch1
if( NUM_CHANNELS_I == 4 ){
*wptr2++ = SAMPLE_SILENCE;//ch2
*wptr3 ++= SAMPLE_SILENCE;//ch3
*wptr4++ = SAMPLE_SILENCE;} //ch4
}
}
else
{
for( i=0; i<framesToCalc; i++ )
{
*wptr++ = *rptr++; //ch1
if( NUM_CHANNELS_I == 4 ){
*wptr2++ = *rptr++;//ch2
*wptr3++ = *rptr++;//ch3
*wptr4 ++= *rptr++;} //ch4
}
}
data->frameIndex += framesToCalc;
return finished;
}
Hope this can help other people. And thank's again, Scott

does python ctypes supports size-0 array?

i have a struct with array[0] inside it.i wonder how can i represent it with ctypes? or if ctypes does not supprt it, are there any other solutions? Any help will be appreciated.
You can represent a struct like this:
struct Test
{
int size;
char arr[0];
};
As:
class Test(ctypes.Structure):
_fields_ = [('size',ctypes.c_int),
('arr',ctypes.c_byte*0)]
But to access the field, you'll need to cast it to a pointer. Assume t is of type ctypes.POINTER(Test):
arr = ctypes.cast(t.contents.arr,POINTER(c_byte))
for i in range(t.contents.size):
print(arr[i])
Tested Windows example
x.h
#ifdef TESTAPI_EXPORTS
#define TESTAPI __declspec(dllexport)
#else
#define TESTAPI __declspec(dllimport)
#endif
struct Test
{
int size;
int arr[0];
};
TESTAPI struct Test* Test_alloc(int size);
TESTAPI void Test_free(struct Test* test);
x.c (Compile with "cl /LD x.c")
#include <stdlib.h>
#define TESTAPI_EXPORTS
#include "x.h"
struct Test* Test_alloc(int size)
{
struct Test* t = malloc(sizeof(struct Test) + size * sizeof(int));
if(t != NULL)
{
int i;
t->size = size;
for(i = 0; i < size; ++i)
t->arr[i] = i*1000+i;
}
return t;
}
void Test_free(struct Test* test)
{
free(test);
}
x.py
from ctypes import *
class Test(Structure):
_fields_ = [('size',c_int),
('arr',c_int*0)]
dll = CDLL('x')
Test_alloc = dll.Test_alloc
Test_alloc.argtypes = [c_int]
Test_alloc.restype = POINTER(Test)
Test_free = dll.Test_free
Test_free.argtypes = [POINTER(Test)]
Test_free.restype = None
t = Test_alloc(10)
print(t.contents.size)
arr = cast(t.contents.arr,POINTER(c_int))
for i in range(t.contents.size):
print(arr[i])
Test_free(t)
Output
10
0
1001
2002
3003
4004
5005
6006
7007
8008
9009

Resources