Linux C code crashes - c

I wrote a C program on the Beaglebone Black to read and write to the 25LC256 (EEPROM). I am able to compile it without any errors or warnings, gcc SPI.c -o SPI, but when I try running it ./SPI, my entire Beaglebone stops working, and I have to reboot it. In fact, the program doesn't even output anything. I have the code print out "Starting" at the begging, but that doesn't even work.
Could anybody see where I might be going wrong ?
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include <stdint.h>
//You need to correctly identify the SPI device bus and number
int write64NVM(int fd, unsigned char data[], int length, unsigned int add);
int read64NVM(int fd, unsigned char to[], int length, unsigned int add);
static const char *device = "/dev/spidev1.0";
int main(){
uint8_t mode=0, bits=8;
uint32_t speed=500000;
int file;
printf("Starting");
if ((file = open(device, O_RDWR))<0){
perror("SPI: Can't open device.");
return -1;
}
if (ioctl(file, SPI_IOC_WR_MODE, &mode)==-1){
perror("SPI: Can't set SPI mode.");
return -1;
}
if (ioctl(file, SPI_IOC_RD_MODE, &mode)==-1){
perror("SPI: Can't get SPI mode.");
return -1;
}
if (ioctl(file, SPI_IOC_WR_BITS_PER_WORD, &bits)==-1){
perror("SPI: Can't set bits per word.");
return -1;
}
if (ioctl(file, SPI_IOC_RD_BITS_PER_WORD, &bits)==-1){
perror("SPI: Can't get bits per word.");
return -1;
}
if(ioctl(file, SPI_IOC_WR_MAX_SPEED_HZ, &speed)==-1){
perror("SPI: Can't set max speed HZ");
return -1;
}
if (ioctl(file, SPI_IOC_RD_MAX_SPEED_HZ, &speed)==-1){
perror("SPI: Can't get max speed HZ.");
return -1;
}
printf("spi mode: 0x%xn", mode);
printf("bits per word: %dn", bits);
printf("max speed: %d Hz (%d KHz)n", speed, speed/1000);
// sending one byte on the MOSI line and receiving the data on MISO
write64NVM(file, "hello", 6, 0);
close(file);
return 0;
}
int write64NVM(int fd, unsigned char data[], int length, unsigned int add)
{
unsigned char InstructionBuffer[1], AddressBuffer[3];
int status;
//DataBuffer = (char *) malloc(length);
struct spi_ioc_transfer xfer[3];
InstructionBuffer[0] = 6; //Set the write enable latch (enable write operations)
AddressBuffer[0] = 2; //Write data to memory array beginning at selected address
AddressBuffer[1] = (add >> 8);
AddressBuffer[2] = (add & 0b11111111);
//DataBuffer = data;
//First Transaction
xfer[0].tx_buf = (unsigned long)InstructionBuffer;
xfer[0].rx_buf = (unsigned long)NULL;
xfer[0].len = 1;
xfer[0].cs_change = 1;
//Second transaction
xfer[1].tx_buf = (unsigned long)AddressBuffer;
xfer[1].rx_buf = (unsigned long)NULL;
xfer[1].len = 3;
xfer[1].cs_change = 0;
//Third transaction
xfer[2].tx_buf = (unsigned long)data;
xfer[2].rx_buf = (unsigned long)NULL;
xfer[2].len = length;
xfer[2].cs_change = 1;
status = ioctl(fd, SPI_IOC_MESSAGE(3), &xfer);
if (status < 0)
{
perror("SPI_IOC_MESSAGE error");
return;
}
return status;
}
int read64NVM(int fd, unsigned char to[], int length, unsigned int add){
//Read Sequence :
//Pull ~CS low
//The 8-bit instruction is transmited to EEPROM followed
//by 16-bit address, with first MSB of the address being a 'dont care'
//bit.
//According to Page 7 Figure 2-1 of the 25LC256.pdf, to read an address from
//EEPROM, the BBB must only send out 2 transactions. The instruction and the address.
//In this case, the instruction is read, so the value of transaction is 3.
//~CS apears to be kept low throughout the entire transaction until data
//has completely been shifted out of EEPROM.
//Like in write64NVM, there are 3 buffers
//unsigned char InstructionBuffer, AddressBuffer[3], DataBuffer[8],
//but the latter will be used to store the Data recieved.
unsigned char InstructionBuffer, AddressBuffer[2], *DataBuffer;
int status;
//DataBuffer = (char *) malloc(length);
struct spi_ioc_transfer xfer[3];
InstructionBuffer = 3; //Read intruction value
//AddressBuffer[0] = 2;
AddressBuffer[0] = add >> 8;
AddressBuffer[1] = add & 0b11111111;
DataBuffer = 0;
//First Transaction
xfer[0].tx_buf = (unsigned long)&InstructionBuffer;
xfer[0].rx_buf = (unsigned long)NULL;
xfer[0].len = 1;
xfer[0].cs_change = 1;
//Second transaction
xfer[1].tx_buf = (unsigned long)AddressBuffer;
xfer[1].rx_buf = (unsigned long)NULL;
xfer[1].len = 2;
xfer[1].cs_change = 0;
//Third transaction
xfer[2].tx_buf = (unsigned long)NULL;
xfer[2].rx_buf = (unsigned long)to;
xfer[2].len = length;
xfer[2].cs_change = 1;
status = ioctl(fd, SPI_IOC_MESSAGE(3), &xfer);
if (status < 0)
{
perror("SPI_IOC_MESSAGE error");
return;
}
return status;
}
Please forgive my poor coding, I'm still a beginner.

Related

Trying to use TCA9548a in C but unable to read or write to sensor in channel

#include <unistd.h> //Needed for I2C port
#include <fcntl.h> //Needed for I2C port
#include <sys/ioctl.h> //Needed for I2C port
#include <linux/i2c-dev.h> //Needed for I2C port
#include <stdio.h>
#include <time.h>
int file_i2c;
int length;
unsigned char buffer[60] = {0};
unsigned char cmdbuffer[60] = {0};
//PRINTS (SENSOR STATUS) IN BINARY
void printBin(unsigned char value)
{
for (int i = sizeof(char) * 7; i >= 0; i--) {
printf("%d", (value & (1 << i )) >> i);
}
putc('\n', stdout);
}
//CREATES DELAY IN MS
void delay(int milli)
{
long pause;
clock_t now,then;
pause = milli * (CLOCKS_PER_SEC / 1000);
now = then = clock();
while ((now-then) < pause) {
now = clock();
}
}
//TIMESTAMPS OUTPUT
void timestamp()
{
time_t ltime;
ltime=time(NULL);
printf("%s", asctime(localtime(&ltime)));
}
//PORT SELECT FOR TCA9548A Addresses range from 0x70-0x77
void portSelect(int port, int addressTCA)
{
if (port > 7 || port < 0)
return;
if (ioctl(file_i2c, I2C_SLAVE, addressTCA) < 0) {
printf("Failed to acquire bus access and/or talk to slave.\n");
return;
}
cmdbuffer[0] = 1 << port;
length = 1;
write(file_i2c, cmdbuffer, length);
}
int main()
{
//----- OPEN THE I2C BUS -----
char *filename = (char*)"/dev/i2c-1";
if ((file_i2c = open(filename, O_RDWR)) < 0) {
//ERROR HANDLING: you can check errno to see what went wrong
printf("Failed to open the i2c bus");
return 0;
}
portSelect(1, 0x70);
//CONFIGURE SLAVE AND ATTEMPT CONNECTION
if (ioctl(file_i2c, I2C_SLAVE, 0x28) < 0) {
printf("Failed to acquire bus access and/or talk to slave.\n");
return 0;
}
flag:
cmdbuffer[0] = 0xAA;
cmdbuffer[1] = 0x00;
cmdbuffer[2] = 0x00;
length = 3;
if (write(file_i2c, cmdbuffer, length) != length)
//write() returns the number of bytes actually written, if it doesn't match then an error occurred (e.g. no response from the device)
{
printf("Failed to write to the i2c bus.\n"); //FAILS HERE
return 0;
}
length = 7; //<<< Number of bytes to read
if (read(file_i2c, buffer, length) != length)
//read() returns the number of bytes actually read, if it doesn't match then an error occurred (e.g. no response from the device)
{
printf("Failed to read from the i2c bus.\n");
} else {
//timestamp();
printf("Status:\n");
printBin(buffer[0]);
int pressure = (buffer[1] << 16) + (buffer[2] << 8) + buffer[3];
int temperature = (buffer[4] << 16) + (buffer[5] << 8) + buffer[6];
printf("Pressure : %d\n", pressure);
printf("Temperature : %d\n\n", temperature);
}
delay(5);
goto flag;
return 0;
}
Current code shown above. I am trying to read from 8 different Honeywell pressure sensors but for the moment I am just trying to get one working. I am able to read/write just fine without the multiplexer. Documentation is unhelpful as it only references Python or Arduino. I have scanned with console and confirmed the addresses of the sensors and mux.

perf_event reports unexpected cache miss amount: accessing N elements in an array incurs 2N cache misses

I'm trying to investigate the relationship between accessing array elements and cache misses. I wrote the following codes.
#include <asm/unistd.h>
#include <linux/perf_event.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <inttypes.h>
static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
int cpu, int group_fd, unsigned long flags) {
int ret;
ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
group_fd, flags);
return ret;
}
int main(int argc, char **argv) {
struct perf_event_attr pe;
long long count;
int fd;
char *chars, c;
uint64_t n = 100000000;
int step = 64;
if (argc > 1) {
step = atoi(argv[1]);
}
chars = malloc(n * sizeof(char));
memset(&pe, 0, sizeof(struct perf_event_attr));
pe.type = PERF_TYPE_HW_CACHE;
pe.size = sizeof(struct perf_event_attr);
pe.config = PERF_COUNT_HW_CACHE_L1D |
PERF_COUNT_HW_CACHE_OP_READ << 8 |
PERF_COUNT_HW_CACHE_RESULT_MISS << 16;
pe.disabled = 1;
pe.exclude_kernel = 1;
pe.exclude_hv = 1;
fd = perf_event_open(&pe, 0, -1, -1, 0);
if (fd == -1) {
fprintf(stderr, "Error opening leader %llx\n", pe.config);
exit(EXIT_FAILURE);
}
for (size_t i = 0; i < n; i++) {
chars[i] = 1;
}
ioctl(fd, PERF_EVENT_IOC_RESET, 0);
ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
// Read from memory
for (size_t i = 0; i < n; i += step) {
c = chars[i];
}
ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
read(fd, &count, sizeof(long long));
printf("%lld\n", count);
close(fd);
free(chars);
}
It is easy to know that only n/step elements in the array chars are accessed and assigned to c. I think the number of cache misses should be n/step if step is larger than the cache line (64 usually). There is no problem when step is small, i.e.,the printed number of count is about n/step. However, if step is a large number, e.g., 1000000, count is equal to about 2n/step. This has confused me for a long time. Could anyone explain this odd result?

Ioctl "can't send spi message: Invalid argument" Beaglebone Black

I am attempting to send 16-bit messages from my beaglebone black on spidev1.0 (bus 1 device 0) to an IC chip TLV5618AC
The chip-select line needs to go from high to low before the shift registers start picking up bits on the falling edge of the clock.
I performed a modified version of spidev_test.c (the original worked fine). Since I need the chip select line to go from high to low between messages - the line ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); will not work because it transmits the data as a single message. Even if I put ioctl() within a for loop it would not work because it is the first and last message.
The following code works
static void transfer(int fd)
{
int ret;
unsigned short buffer[1];
int zero = 0;
FILE *iFile = fopen("firsttest.bin", "r");
if (iFile == NULL)
{
printf("Cannot open file \n");
exit(0);
}
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)zero,
.rx_buf = (unsigned long)zero,
.len = 2,
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};
while(!feof(iFile)){
fread(buffer,2,1,iFile);
unsigned short *tx = buffer;
unsigned short rx[1] = {0, };
tr.tx_buf = (unsigned long)tx;
tr.rx_buf = (unsigned long)rx;
int size = ARRAY_SIZE(tx);
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
pabort("can't send spi message");
for (ret = 0; ret < 1; ret++) {
printf("0x%04x\n", tx[ret]);
}
}
}
This second block of code does not
{
int ret;
unsigned short buffer[1];
int zero = 0;
FILE *iFile = fopen("firsttest.bin", "r");
if (iFile == NULL)
{
printf("Cannot open file \n");
exit(0);
}
struct spi_ioc_transfer tr[100];
unsigned short *p = (unsigned short*) calloc(100, sizeof(unsigned short));
unsigned short *p2 = (unsigned short*) calloc(100, sizeof(unsigned short));
while(!feof(iFile)){
unsigned short *tx = p2;
unsigned short *rx=p;
for(int j = 0; j< 100; j++){
fread(buffer,2,1,iFile);
tx = (unsigned short*) &buffer+j;
tr[j].tx_buf = (unsigned long)tx;
tr[j].rx_buf = 0;
tr[j].len = 2;/* Total length of message in bytes*/
tr[j].delay_usecs = delay;
tr[j].speed_hz = speed;
tr[j].bits_per_word = bits;
tr[j].cs_change = 1;
}
ret = ioctl(fd, SPI_IOC_MESSAGE(100), &tr);
if (ret < 1)
pabort("can't send spi message");
for(int v = 0; v<100; v++){
printf("0x%04x\n", rx);
}
}
free(p);
}
The second block of code yield this error
"can't send spi message: Invalid argument"
Since it is an invalid argument, I tried passing in '&tr' as well as 'tr' to no avail. Any input would be appreciated.
EDIT: So I resolved to use the first code which worked. I guess there is no reason to send large transfers. My system is fast enough to where the voltages are fast enough to effectively be real time!! Thanks for the help. (I also cleaned up my code a lot to make it easier to read!)
add memset(&tr, 0, sizeof(tr)); after struct spi_ioc_transfer tr
https://community.nxp.com/thread/482375
Looking through this, it occurs to me that you may not be defining your tr[j].rx_buf correctly, and this would lead to the invalid argument. There needs to be an allocated storage which I assume is *p, but you aren't associating that with the tr argument.

I2C IOCTL Write Failure

Hey I am trying to write a user space application to move some data to an I2C for an embedded system running PetaLinux, an operating system for embedded Linux, although I do not think that is what is affecting the issue. I am getting a Connection timeout and a segmentation fault.
The function has macros that direct it to write to the first I2C bus. I specify the data that I want to write in main and pass it to i2c_write, which then passes it to i2c_ioctl_write.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#define I2C_ADAPTER "/dev/i2c-0"
#define I2C_DEVICE 0x00
#define REG_ADDR 0x00
int i2c_ioctl_write (int fd, uint8_t dev, uint8_t regaddr, uint16_t *data)
{
printf("i2c_ioctl_write\n");
int i, j = 0;
int ret;
uint8_t *buf;
buf = malloc(1 + 2 * (sizeof(data) / sizeof(data[0])));
if (buf == NULL) {
return -ENOMEM;
}
printf("\tBuffer Allocation Successful...\n");
buf[j ++] = regaddr;
for (i = 0; i < (sizeof(data) / sizeof(data[0])); i ++) {
buf[j ++] = (data[i] & 0xff00) >> 8;
buf[j ++] = data[i] & 0xff;
}
printf("\tBuffer Setup Successful...\n");
struct i2c_msg messages[] = {
{
.addr = dev,
.buf = buf,
.len = sizeof(buf) / sizeof(buf[0]),
},
};
printf("\tSetup I2C Messages...\n");
struct i2c_rdwr_ioctl_data payload = {
.msgs = messages,
.nmsgs = sizeof(messages) / sizeof(messages[0]),
};
printf("\tSetup I2C IOCTL Payload...\n");
ret = ioctl(fd, I2C_RDWR, &payload);
printf("\tWrote with IOCTL...\n");
if (ret < 0) {
ret = -errno;
}
free (buf);
return ret;
}
int i2c_ioctl_smbus_write (int fd, uint8_t dev, uint8_t regaddr, uint16_t *data)
{
printf("i2c_ioctl_smbus_write\n");
int i, j = 0;
int ret;
uint8_t *buf;
buf = malloc(2 * (sizeof(data) / sizeof(data[0])));
if (buf == NULL) {
return -ENOMEM;
}
for (i = 0; i < (sizeof(data) / sizeof(data[0])); i ++) {
buf[j ++] = (data[i] & 0xff00) >> 8;
buf[j ++] = data[i] & 0xff;
}
struct i2c_smbus_ioctl_data payload = {
.read_write = I2C_SMBUS_WRITE,
.size = I2C_SMBUS_WORD_DATA,
.command = regaddr,
.data = (void *) buf,
};
ret = ioctl (fd, I2C_SLAVE_FORCE, dev);
if (ret < 0)
{
ret = -errno;
goto exit;
}
ret = ioctl (fd, I2C_SMBUS, &payload);
if (ret < 0)
{
ret = -errno;
goto exit;
}
exit:
free(buf);
return ret;
}
int i2c_write (int fd, uint8_t dev, uint8_t regaddr, uint16_t *data)
{
printf("i2x_write\n");
uint64_t funcs;
if (ioctl(fd, I2C_FUNCS, &funcs) < 0) {
return -errno;
}
if (funcs & I2C_FUNC_I2C) {
return i2c_ioctl_write (fd, dev, regaddr, data);
} else if (funcs & I2C_FUNC_SMBUS_WORD_DATA) {
return i2c_ioctl_smbus_write (fd, dev, regaddr, data);
} else {
return -ENOSYS;
}
}
int main (int argc, char *argv[])
{
printf("main\n");
uint8_t regaddr;
int fd;
int ret = 0;
uint16_t data[] = {1, 2, 4};
fd = open(I2C_ADAPTER, O_RDWR | O_NONBLOCK);
ret = i2c_write(fd, I2C_DEVICE, REG_ADDR, data);
close(fd);
if (ret) {
fprintf (stderr, "%s.\n", strerror(-ret));
}
free(data);
return ret;
}
When I run the program on QEMU I get the following output:
main
i2x_write
i2c_ioctl_write
Buffer Allocation Successful...
Buffer Setup Successful...
Setup I2C Messages
Setup I2C IOCTL Payload
cdns-i2c e0004000.i2c: timeout waiting on completion
Wrote with IOCTL
Connection timed out.
Segmentation fault
I assume it is failing on the line
ret = ioctl(fd, I2C_RDWR, &payload);
but I am not sure why. Was the payload constructed improperly?
Update: Here is the current code:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#define I2C_ADAPTER "/dev/i2c-0"
#define I2C_DEVICE 0x00
int main (int argc, char *argv[])
{
int fd;
int ret = 0;
fd = open(I2C_ADAPTER, O_RDWR | O_NONBLOCK);
uint64_t funcs;
int addr = 0X00;
if (ioctl(fd, I2C_SLAVE, addr) < 0) {
/* ERROR HANDLING; you can check errno to see what went wrong */
printf("Cannot setup as slave");
exit(1);
}
if (ioctl(fd, I2C_FUNCS, &funcs) < 0) {
printf("ioctl failed");
return -errno;
}
printf("funcs & I2C_FUNC_I2C: %llu\n", funcs & I2C_FUNC_I2C);
printf("funcs & I2C_FUNC_SMBUS_WORD_DATA: %llu\n", funcs & I2C_FUNC_SMBUS_WORD_DATA);
__u8 reg = 0x10;
__s32 res;
if (funcs & I2C_FUNC_I2C) {
char buf[10];
printf("Attempting to write to I2C bus via I2C protocol...\n");
buf[0] = reg;
buf[1] = 0x43;
buf[2] = 0x65;
int bytes_written = write(fd, buf, 3);
if(bytes_written != 3) {
printf("Wrote %d bytes", bytes_written);
printf("\tFailed to write to I2C Bus\n");
close(fd);
return -1;
}
else {
printf("\tSuccesful write to I2C Bus\n");
}
char buf2[10];
printf("Attempting to read from I2C bus via I2C protocol...\n");
if(read(fd, buf2, 1) != 1) {
printf("\tFailed to do I2C read from Bus\n");
close(fd);
return -1;
}
else {
printf("\tRead successful. Comparing read results from original write buffer...");
printf("\t\tWritten value: %c", buf[0]);
printf("\t\tRead value: %c", buf2[0]);
}
return 0;
} else if (funcs & I2C_FUNC_SMBUS_WORD_DATA) {
printf("Attempting to write to I2C bus via SMBus protocol...\n");
//res = i2c_smbus_write_word_data(fd, REG_ADDR, 0x6543);
res = 1;
if(res < 0) {
printf("\tFailed to write to I2C Bus\n");
close(fd);
return -1;
}
else {
printf("\tSuccesful write to I2C Bus\n");
}
//res = i2c_smbus_read_word_data(fd, REG_ADDR);
if(res < 0) {
printf("\tFailed to read from I2C Bus\n");
close(fd);
return -1;
}
else {
printf("\tRead successful. Comparing read results from original write buffer...");
printf("\t\tWritten value: %c", 0x6543);
printf("\t\tRead value: %c", res);
}
} else {
printf("Cannot write to I2C");
return -ENOSYS;
}
close(fd);
if (ret) {
fprintf (stderr, "%s.\n", strerror(-ret));
}
return ret;
}
I was able to get rid of the seg fault by removing free(), so thanks there. I have pinpointed the exact issue of the timeout which occurs in the Cadence I2C Driver here:
https://github.com/Xilinx/linux-xlnx/blob/3f3c7b60919d56119a68813998d3005bca501a40/drivers/i2c/busses/i2c-cadence.c#L825
which is still occurring.
As mentioned, there is probably some issue with the way I am writing to slave causing the slave to not send ACK, resulting in a timeout. I am not sure which registers I will need to write what to. I have a feeling the I2C_DEVICE macro and addr and reg variables will need to be changed.
cdns-i2c e0004000.i2c: timeout waiting on completion
It seems that i2c driver (cdns-i2s) doesnt recieves the acknowledgment from the slave. It may occur as you are using I2C-slave address as 0x00 which is a general call address. While using general call address the second byte that is sent has a special purpose which is mentioned in the i2c-specification (section 3.1.13).
If you use general call address you need to follow the specification or else Try using the exact i2c slave address instead of general call address(0x00).

Raspberry PI uint8_t alignment

I got this kind of problem with using uint8_t as array which is passed to my transferring function. At the moment of passing from main function to transfer it changes size to 4 elements. Same thing with array which I create inside my transfer function, even though I manually create another array to send my values with passed length from main function. I understand it is because of data alignment and padding on my processor. Is there any way to solve it? Or I'm printing it wrong.
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(uint8_t))
static const char *device = "/dev/spidev0.0";
static uint8_t mode;
static uint8_t bits = 8;
static uint32_t speed = 1000000;
static uint16_t delay;
static void transfer(int fd, const uint8_t *pass, size_t arsize)
{
int ret,i,k;
printf(" rozmiar tabpass=%d ", arsize);
uint8_t *rx = (uint8_t*) malloc(arsize * sizeof(uint8_t));
//this is where I create rx with arsize lenght
uint8_t *tx = (uint8_t*) malloc(arsize * sizeof(uint8_t));
for (i = 0; i < arsize; i++){
*(rx + i) = 0;
*(tx + i) = *(pass + i);
}
for (k = 0; k < (sizeof (pass) / sizeof (pass[0])); k++) {
printf(" a%X\n ", pass[k]);
//here I check length of passed array
}
for (k = 0; k < (sizeof (tx) / sizeof (tx[0])); k++) {
printf(" b%X\n ", tx[k]);
// I check length of newly created array, should be equal to array size
}
printf(" rozmiar tabtx=%d ", ARRAY_SIZE(tx));
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = arsize,
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
.cs_change = 0,
};
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
printf(" rozmiar tabrx=%d ", ARRAY_SIZE(rx));
//here it prints size of array equals 4
for (ret = 0; ret < arsize; ret++) {
if (!(ret % 6))
puts("");
printf("%d. %.2X ", ret, rx[ret]);
}
puts("");
tr.cs_change = 1;
}
int main(int argc, char *argv[])
{
int ret = 0;
int fd;
fd = open(device, O_RDWR);
/*
* spi mode
*/
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
/*
* bits per word
*/
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
/*
* max speed hz
*/
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
printf("spi mode: %d\n", mode);
printf("bits per word: %d\n", bits);
printf("max speed: %d Hz (%d KHz)\n", speed, speed / 1000);
uint8_t tx1[] = {
0x0, 0x1b, 0xa5
};
transfer(fd, tx1, ARRAY_SIZE(tx1));
uint8_t tx2[] = {
0x0, 0x33, 0x30
};
printf(" %d. ", ARRAY_SIZE(tx2));
transfer(fd, tx2, ARRAY_SIZE(tx2));
uint8_t tx3[] = {
0x0, 0x52, 0x90
};
transfer(fd, tx3, ARRAY_SIZE(tx3));
uint8_t tx4[] = {
0x80, 0x60
};
printf(" %d. ", ARRAY_SIZE(tx4));
transfer(fd, tx4, ARRAY_SIZE(tx4));
close(fd);
return ret;
}
For the sizeof operator to give the actual size of the array, you need to:
Allocate the array statically
Refer to the array within its scope of declaration
For example:
void func()
{
int arr[10];
int total_size = sizeof(arr);
int num_of_elements = sizeof(arr)/sizeof(*arr);
...
}
An example of when the array is not statically allocated:
void func()
{
int* arr = malloc(sizeof(int)*10);
int total_size = sizeof(arr); // will give you the size of 'int*'
...
}
An example of when the array is not within its scope of declaration:
void func(int arr[]) // same as 'int* arr'
{
int total_size = sizeof(arr); // will give you the size of 'int*'
...
}

Resources