add AVR Studio pgm_read_byte function to MiKroc (Electronica) - pgm

I have a program in AVR Studio V4 with the following code:
#include <avr/pgmspace.h>
void nlcd_Putc(unsigned char c)
{
unsigned char i;
if (c>127) c=c-64;
for (i = 0; i < 5; i++ )
{
nlcd_SendByte(DATA_LCD_MODE,pgm_read_byte(&(nlcd_Font[c-32][i])));
}
nlcd_SendByte(DATA_LCD_MODE,0x00);
}
So when i want to run this code in MiKroC for AVR i get the following error:
128 324 Undeclared identifier 'pgm_read_byte' in expression MyProject.c
Should I add the header avr/pgmspace.h To MiKroc For AVR, or what is the equivalent header to avr/pgmspace.h in Mikroc For AVR?
Thanks a lot.

by addinf this codes to header :
typedef signed char int8;
typedef unsigned char uint8;
typedef signed int int16;
typedef unsigned int uint16;
typedef signed long int int32;
typedef unsigned long int uint32;
//-----------------------
#define PGM_P char flash *
#define PROGMEM flash
#define const flash
#define PSTR(x) x
#define EEMEM eeprom
#define pgm_read_byte(x) (*((uint8 flash *)(x)))
#define pgm_read_word(x) (*((uint16 flash *)(x)))
#define pgm_read_float(x) (*((uint32 flash *)(x)))
#define pgm_read_byte_near(x) (*((uint8 flash *)(x)))

Related

Stuck with netlink, connektor, socket and co

I'm completely new to netlink & co. and I am trying to establisch a connection from user space to the w1-kernel module of a raspberry pi.
Unfortunately the documentation i found is spotty and contradictory.
Here some of the things not clear to me:
basic communication is:
generate a socket: socket()
int s = socket(AF_NETLINK,SOCK_DGRAM, NETLINK_CONNECTOR);
bind it to a local name: bind()
int b = bind(s,(sockaddr*)&sa,sizeof(sa));
with
sa.nl_family=AF_NETLINK;
sa.nl_pid=getpid();//0?
sa.nl_groups=0; //23? -1?
create the message
send it: send()? sendmsg()?
wait for answer: poll()
read answer: recv()
+In examples i found (w1d.c and ucon.c) they use the send() command (not sendmsg) without a connect(), even though the man pages of send say that wouldnt work.
+I am not clear about the structure of the message:
send can send any buffer (char*)
netlink expects a struct nlmsghdr header;
connector expects a struct cn_msg header.
w1_netlink expects a w1_netlink_msg header and w1_netlink_cmd data.
Do i need all headers in a row? Ther are 2 sequence / message number variables, one in nlmsghdr and on in cn_msg???
The test program i wrote is not producing the result i expect: every thing works withour producing an error but i am getting no answer :-(
#include <iostream>
#include <linux/netlink.h>
#include <sys/types.h>
#include <sys/socket.h>
#include<sys/poll.h>
#include <unistd.h>
#include<cstring>
#include "w1_netlink.h"
__u32 nl_seq;
static int netlink_send(int s, struct cn_msg *msg) //copy from (ucon.c)
{
struct nlmsghdr *nlh;
unsigned int size;
int err;
char buf[128];
struct cn_msg *m;
size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len);
nlh = (struct nlmsghdr *)buf;
nlh->nlmsg_seq = nl_seq++;
nlh->nlmsg_pid = getpid();
nlh->nlmsg_type = NLMSG_DONE;
nlh->nlmsg_len = size;
nlh->nlmsg_flags = 0;
m = (cn_msg*) NLMSG_DATA(nlh);
memcpy(m, msg, sizeof(*m) + msg->len);
err = send(s, nlh, size, 0);
return err;
}
int main(int argc, char *argv[])
{
nl_seq=0;
int s = socket(AF_NETLINK,SOCK_DGRAM, NETLINK_CONNECTOR);
if(s==-1) {std::cout<<"no socket"; return s;};
std::cout<<"socket "<<s;
sockaddr_nl sa;
sa.nl_family=AF_NETLINK;
sa.nl_pid=0;//getpid();
sa.nl_groups=0;
int b = bind(s,(sockaddr*)&sa,sizeof(sa));
if(b==-1){std::cout<<"bind error";return b;}; //prints 3
std::cout<<"bind "<<b; //prints 0
int si=sizeof(struct cn_msg)+sizeof(struct w1_netlink_msg)+sizeof(w1_netlink_cmd);
char * buf;
buf=(char *)malloc(1024);
memset(buf,0,1024);
cn_msg *cnh = (cn_msg*)buf;
w1_netlink_msg* wnh=(w1_netlink_msg*)&cnh->data;
w1_netlink_cmd* wcmd = (w1_netlink_cmd*)&wnh->data;
cnh->id.idx=CN_W1_IDX;
cnh->id.val=CN_W1_VAL;
cnh->seq=nl_seq;
cnh->flags=0;
wnh->type=W1_LIST_MASTERS;
wnh->len=0;
cnh->len=sizeof(struct w1_netlink_msg)+sizeof(w1_netlink_cmd);
int len=netlink_send(s,cnh);
std::cout<<"send "<<len<<" "<<(int)wnh->status; //prints 52 0
pollfd pfd;
pfd.fd=s;
pfd.events=POLLIN;
pfd.revents=0;
int p=0;
while(p<1) {
p=poll(&pfd,1,1000);
std::cout<<"poll "<<p<<pfd.revents; //prints 0 0 in infinite loop
std::cout.flush();
};
memset(wcmd,0,128);
len=recv(s,buf,255,0);
std::cout<<"recv "<<len;
close(s);
return 0;
}
Result is socket 3 bind 0 send 52 0 poll 00 poll 00 ...
Thanks

why setuid fails after capset is used?

trying to figure out the linux capabilities interface, i came across with an unexpected issue (for me at least). When seting the capabilities of a process with the capset syscall the kernel rejects a change of userid with the setuid syscall. Does anybody know why setuid fails?
This is code i wrote to test this behavior:
#undef _POSIX_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/capability.h>
#include <sys/capability.h>
#include <string.h>
int main(int argc, char** argv){
struct __user_cap_header_struct cap_header;
struct __user_cap_data_struct cap_data;
int cap_res;
FILE *file;
int sockfd;
cap_header.pid = getpid();
cap_header.version = _LINUX_CAPABILITY_VERSION_1;
__u32 cap_mask = 0;
cap_mask |= (1 << CAP_DAC_OVERRIDE);
cap_mask |= (1 << CAP_SETUID);
printf("You selected mask: %x\n", cap_mask);
cap_data.effective = cap_mask;
cap_data.permitted = cap_mask;
cap_data.inheritable = cap_mask;
cap_res = capset(&cap_header, &cap_data);
if(cap_res < 0){
printf("Trying to apply mask: FAIL\n", cap_mask);
} else {
printf("Capability set correctly\n");
}
int uid = atol(argv[1]);
int setuid_res = setuid(uid);
if (setuid_res == -1){
printf("7w7\n");
} else {
printf("UID set correctly\n");
}
}
compiled with:
$ gcc -g test1.c -o test1
Output is (for user id: 1000)
$ # ./test1 1000
You selected mask: 2
Capability set correctly
7w7
I think you might be missing a couple of steps in your question:
How do you give the binary some privilege?
It looks like you are trying to use cap_dac_override to achieve what cap_setuid is intended for.
Rewriting the program as follows:
#undef _POSIX_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/capability.h>
#include <sys/capability.h>
#include <string.h>
int main(int argc, char** argv){
struct __user_cap_header_struct cap_header;
struct __user_cap_data_struct cap_data;
int cap_res;
// need to start from known data. C does not guarantee these are
// zero filled by default. You could declare them static to get
// that.
memset(&cap_header, 0, sizeof(cap_header));
memset(&cap_data, 0, sizeof(cap_data));
cap_header.pid = getpid();
cap_header.version = _LINUX_CAPABILITY_VERSION_1;
__u32 cap_mask = 0;
cap_mask |= (1 << CAP_SETUID);
printf("You selected mask: %x\n", cap_mask);
cap_data.effective = cap_mask;
cap_data.permitted = cap_mask;
// not needed: cap_data.inheritable = cap_mask;
cap_res = capset(&cap_header, &cap_data);
if(cap_res < 0){
printf("Trying to apply mask: FAIL\n", cap_mask);
exit(1);
} else {
printf("Capability set correctly\n");
}
if (argc != 2) {
printf("usage: %s <uid>\n", argv[0]);
exit(1);
}
int uid = atol(argv[1]);
int setuid_res = setuid(uid);
if (setuid_res == -1){
printf("7w7\n");
} else {
printf("UID set correctly to %d\n", uid);
}
}
You can run the program like this:
$ sudo ./test1 1000
You selected mask: 80
Capability set correctly
UID set correctly to 1000
Or, using a file capability:
$ sudo setcap cap_setuid=p ./test1
$ ./test1 1000
You selected mask: 80
Capability set correctly
UID set correctly to 1000
This will work if you want to use the first 32 capabilities. However, there are ~40 of them under Linux at present, so I'd suggest you look into using the libcap API instead which figures out all of the kernel ABI details for you.

STM32 GSM AT command response parser

I am sending AT command to get IMEI no.
char CGSN[] = "AT+CGSN\r\n";
// in while loop
HAL_UART_Transmit(&huart2,(uint8_t *)CGSN, sizeof(CGSN),100);
HAL_Delay(1000);
HAL_UART_Receive_IT(&huart2,(uint8_t *)&ch,1);
// Callback
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART2){
if(buf[i]!=13){
buf[i]=ch;
i++;
}
}
HAL_UART_Receive_IT(&huart2,(uint8_t *)&ch,1);
buf[i]=0;
}
the response stored in buffer is - \r\n9876543212345\r\n\r\nOK\r\n
What is best way to receive response and filter out n"9876543212345" & "OK" and store separately in a array to further process
Thanks
You can use sscanf for this purpose. Below is the quick implementation of the scenario in C.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(void) {
unsigned long a;
char array[10];
char string[] = "\r\n9876543212345\r\n\r\nOK\r\n";
sscanf(string , "\r\n%ld\r\n\r\n%s\r\n", &a, array);
printf("%ld %s\n", a, array);
return 0;
}
Problem is simple! Your buf[] dont include '\r' (in decimal 13).
Correct value buf[] is "AT+CGSN\n9876543212345\n\nOK\n\0".

perl match function for C program

Trying to use perl API functions in C program. Couldn't find the function to do regular expression match. Wish there is a function like regexmatch in the following program.
#include <EXTERN.h> /* from the Perl distribution */
#include <perl.h> /* from the Perl distribution */
#include <sys/time.h>
typedef unsigned long ulong;
static PerlInterpreter *my_perl; /*** The Perl interpreter ***/
int main(int argc, char **argv, char **env) {
int numOfArgs = 0;
PERL_SYS_INIT3(&numOfArgs, NULL, NULL);
my_perl = perl_alloc();
perl_construct(my_perl);
SV* str = newSVpv(argv[1], strlen(argv[1]));
if (regexmatch(str, "/hi (\S+)/")) {
printf("found a match\n");
}
return 0;
}
I know it's possible to use pcre library, just wonder if it's possible to get it from perl library here (libperl.so.5.14.2 on ubuntu 12.04)
Thanks!
UPDATE 1:
Did some google search and got the following simple program compiling. But when I ran the program as ./a.out ping pin, it gave "Segmentation fault" in the "pregcomp" function. Not sure why.
#include <EXTERN.h> /* from the Perl distribution */
#include <perl.h> /* from the Perl distribution */
#include <sys/time.h>
#include <embed.h>
typedef unsigned long ulong;
static PerlInterpreter *my_perl; /*** The Perl interpreter ***/
struct REGEXP * const engine;
int main(int argc, char **argv, char **env) {
int numOfArgs = 0;
PERL_SYS_INIT3(&numOfArgs, NULL, NULL);
my_perl = perl_alloc();
perl_construct(my_perl);
SV* reStr = newSVpv(argv[2], strlen(argv[2]));
printf("compiling regexp\n");
REGEXP * const compiled_regex = pregcomp(reStr, 0);
printf("execing regexp\n");
int len = strlen(argv[1]);
pregexec(compiled_regex, argv[1], argv[1] + len, argv[1], 5, NULL, 0);
return 0;
}
Don't mess with Perl's private internals. Call a Perl sub that uses the match operator.
Say you previously compiled the following in your interpreter (using eval_pv),
sub regex_match { $_[0] =~ $_[1] }
Then you can call
static bool regex_match_sv(SV* str, SV* re) {
dSP;
bool matched;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(str);
XPUSHs(re);
PUTBACK;
call_pv("regex_match", G_SCALAR);
SPAGAIN;
matched = SvTRUE(POPs);
PUTBACK;
FREETMPS;
LEAVE;
return matched;
}

ADXL345 atmega16

i just started the project which requiers to connect ADXL345 to my Atmega16. I want to put device id on screen and read axis. So far i cant communicate with ADXL345. ON LCD only appears 0 I would be gratefull for any help.
#include <avr/io.h>
#include <stdlib.h>
#include <util/delay.h>
#include "hd44780.h"
#define F_CPU 1000000UL
/*-----------------------Rejestry ADXL345---------------------*/
char POWER_CTL = 0x2D; //Power Control Register 0x08 measurement
char DATA_FORMAT = 0x31;
char BW_RATE = 0X2C;
char FIFO = 0x38; //fifo ctl
char DATAX0 = 0x32; //X-Axis Data 0
char DATAX1 = 0x33; //X-Axis Data 1
char DATAY0 = 0x34; //Y-Axis Data 0
char DATAY1 = 0x35; //Y-Axis Data 1
char DATAZ0 = 0x36; //Z-Axis Data 0
char DATAZ1 = 0x37; //Z-Axis Data 1
char DEVICEID = 0x00;
#define Read_Byte_SPI( addr ) ADXL_write( 0x80 | addr , 0xFF );
/*------------------PORTY SPI---------------*/
#define SPI_CS PB4
#define DDR_SPI DDRB
#define DD_MOSI PB5
#define DD_MIOS PB6
#define DD_SCK PB7
/*vcc<->vs*/
//--------------------------------------Funkcje-------------------
unsigned int init_port(void) //ports 4 lcd
{DDRD =0x00; PORTD =0x07 ; }
/*function 4 lcd*/
static void lcd( int a){ LCD_LOCATE(2,0); char buff[2]; char tab[2]; /*itoa(a,buff,10);*/ sprintf(a, %d", buff); lcd_puts(buff);
}
/**
* This writes to a register with the data passed to the address passed
* #param unsigned char cReg - the address of the register you wish to write to
* #param unsigned char cData - the data you wish to write to the register
*/
unsigned char ADXL_write(unsigned char cReg, unsigned char cData){
set_spics();
/* Start transmission send register */
SPDR = cReg;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)))
{ /* NOOP */ }
SPDR = cData;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)))
{ /* NOOP */ }
clear_spics();
return SPDR;
}
uint8_t ADXL_read(unsigned char addr) { // read ADXL345 - 128+ addrs, back 8 bits - found this in another topic
int8_t ans;
set_spics();
SPDR = 0x08 | addr;
loop_until_bit_is_set(SPSR, SPIF);
SPDR = 0xFF;
loop_until_bit_is_set(SPSR, SPIF);
ans = SPDR;
clear_spics();
return(ans);}
//inicjalizacjia SPI
void Init_SPI(){
// make the MOSI, SCK, and SS pins outputs
DDRB |= ( 1 << DD_MOSI ) | ( 1 << DD_SCK ) | ( 1 << SPI_CS );
DDRB &= ~( 1 << DD_MIOS );
/* Enable SPI, Master, set clock rate fck/128 */
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1);
}
//Control SS=CHIP SELECT ADXL345
void clear_spics(){
PORTB |= _BV(SPI_CS); // high
_delay_ms(30);}
void set_spics(){
PORTB &=~ _BV(SPI_CS); // low
_delay_ms(30);}
void ADXL_init(void){
//init ADXL
ADXL_write(DATA_FORMAT,0x08); //pełna rozdzielczość DATASHEET STRONA 26 4SPI
ADXL_write(BW_RATE, 0x0A) ; //100hz
ADXL_write(POWER_CTL,0x08);
ADXL_write(FIFO, 0); //FIFO Wylacozny
}
/*------------------------główna petla---------------------------*/
int main(void)
{
/* tab for strings */
char str1[] = "Czujnik ADXL 345";
/* init lcd*/
lcd_init();
/* LCD UP */
LCD_DISPLAY(LCDDISPLAY);
LCD_CLEAR;
LCD_LOCATE(1,1);
lcd_puts(str1);
init_port();/*port init*/
Init_SPI();//SPIUP
_delay_ms(50);
ADXL_init(); //ADXL345 config
_delay_ms(50);
while(1)
{
int8_t k;
k=Read_Byte_SPI( DEVICEID );
lcd(k);
_delay_ms(5000);
k=ADXL_read(DATAX0);
lcd(k);
_delay_ms(5000);
}
`>