I just wondered if someone could give me some pointers (no pun intended) how to do this?
I want to set aside 4GB of ram in order to map numbers to memory which saves me traversing a linked list checking if they are there.
So instead of having (1,2,3,4,8,34,543,2343) and traversing 8 elements to verify that '2343' is in the list, i want to be able to look up the key '2343' in O(1) time?
Thanks in advance
If you only need to check if the number exists in the list, the you can try to make a Bitmap.
If the numbers are going to be sparsely spread out over a large range like 100,000 values in the range 0-4billion then a Hashtable would be faster. For a C implementation of a Hashtable take a look at GLib's Hashtable.
A Bitmap could hold numbers 0-4,294,967,295 using only 512Mbytes of ram.
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#define BITMAP_TEST 1
#define BITMAP_32_WORD 1
typedef struct Bitmap Bitmap;
#if BITMAP_32_WORD
#define BITWORD_BITS_SHIFT 5
typedef uint32_t Bitword;
#else
#define BITWORD_BITS_SHIFT 6
typedef uint64_t Bitword;
#endif
#define BITWORD_BITS (sizeof(Bitword) * 8)
#define BITWORD_BITS_MASK (BITWORD_BITS - 1)
#define BITWORD_MULT(bit) ((bit + (BITWORD_BITS_MASK)) & ~(BITWORD_BITS_MASK))
#define BITWORD_TEST(bword, bit) ((bword >> bit) & 1)
#define BITMAP_WORD_COUNT(bit) (BITWORD_MULT(bit) >> BITWORD_BITS_SHIFT)
struct Bitmap {
size_t length;
Bitword *bitmap;
};
extern Bitmap *bitmap_new(size_t len) {
Bitmap *bitmap = malloc(sizeof(Bitmap));
bitmap->length = len;
bitmap->bitmap = calloc(BITMAP_WORD_COUNT(len),sizeof(Bitword));
return bitmap;
}
extern void bitmap_free(Bitmap *bitmap) {
free(bitmap->bitmap);
free(bitmap);
}
extern void bitmap_set(Bitmap *bitmap, size_t bit) {
assert(bit < bitmap->length);
bitmap->bitmap[(bit >> BITWORD_BITS_SHIFT)] |= ((Bitword)1 << (bit & BITWORD_BITS_MASK));
}
extern void bitmap_unset(Bitmap *bitmap, size_t bit) {
assert(bit < bitmap->length);
bitmap->bitmap[(bit >> BITWORD_BITS_SHIFT)] &= ~((Bitword)1 << (bit & BITWORD_BITS_MASK));
}
extern bool bitmap_test(Bitmap *bitmap, size_t bit) {
assert(bit < bitmap->length);
Bitword bword = bitmap->bitmap[(bit >> BITWORD_BITS_SHIFT)];
return BITWORD_TEST(bword, (bit & BITWORD_BITS_MASK));
}
#ifdef BITMAP_TEST
#include <stdio.h>
#define MAX_VALUE (2343 + 1)
static const uint32_t test_values[] = { 1,2,3,4,8,34,543,2343 };
#define test_values_len (sizeof(test_values)/sizeof(uint32_t))
static void set_values(Bitmap *bitmap, const uint32_t *values, int len) {
int i;
for(i=0; i < len; i++) {
bitmap_set(bitmap, values[i]);
}
}
static void unset_values(Bitmap *bitmap, const uint32_t *values, int len) {
int i;
for(i=0; i < len; i++) {
bitmap_unset(bitmap, values[i]);
}
}
static void check_values(Bitmap *bitmap, const uint32_t *values, int len, bool is_set) {
int i;
for(i=0; i < len; i++) {
assert(bitmap_test(bitmap, values[i]) == is_set);
}
}
int main(int argc, char *argv[]) {
Bitmap *bitmap = bitmap_new(MAX_VALUE);
set_values(bitmap, test_values, test_values_len);
check_values(bitmap, test_values, test_values_len, true);
unset_values(bitmap, test_values, test_values_len);
check_values(bitmap, test_values, test_values_len, false);
bitmap_free(bitmap);
return 0;
}
#endif
If the numbers are 32 bits you don't even need hashing, just use an array.
I would advise embedding Lua in your project. Easy to embed and completely ANSI C with one very flexible garbage collected data structure (a Lua table/aka hashmap). You can always strip out the bits that you don't need, but even if you don't Lua is tiny.
Lua has a stack based API which isn't too hard to follow:
lua_State *L = luaL_newstate(); // make a new lua state
lua_newtable(L); // pushes a new table to the top of the stack (position 1)
// storing values
lua_pushinteger(2343); // key: 2343
lua_pushboolean(1); // value: true
lua_settable(L, 1); // pop key/value, store in table at position 1
// retrieving values
lua_pushinteger(2343); // key we're looking for
lua_gettable(L, 1); // get from table at top of stack - 2; pops key
if (lua_toboolean(L, -1)) // is it a true value?
{
// executes; we know 2343 is true as we pushed it just above
}
lua_pop(L, 1); // pop it off the stack; only our table remains
And you can iterate over the values as well, possibly doing away with the need of your linked list (but the order of the iteration is non-determinate). Full manual here.
A hashtable is actually only O(1) when there are no keys that have the same hash.
For an easy short version of a hashtable in C look here:
http://pokristensson.com/strmap.html
Related
so I've got a buggy C file in which i need to find an exploit. I have found a bug when accessing the following struct:
#define BOARD_SIZE 10
typedef int (*turn_function_t)(struct board *);
typedef void (*win_function_t)(struct board *);
struct board {
uint8_t f1[BOARD_SIZE][BOARD_SIZE];
uint8_t f2[BOARD_SIZE][BOARD_SIZE];
win_function_t win;
turn_function_t turn;
int avail;
};
int do_shot(struct board *board, int strength, int x, int y) {
if(!(x >= 0 && x <= BOARD_SIZE && y >= 0 && y <= BOARD_SIZE)) {
return SHOT_ERR_EINVAL;
}
/* If there was already a sunken ship, return error */
if(board->f1[x][y] && !board->f2[x][y])
return SHOT_ERR_SUNKEN;
/* Now perform shot */
if(!board->f2[x][y])
return SHOT_WATER;
board->f2[x][y] -= strength;
if(!board->f2[x][y])
return SHOT_SUNKEN;
return SHOT_HIT;
}
The bug I found is a wrong index check when accessing array f2. I can chose the index as input (index can be anything from 0 to 10 inclusive). I need to find a way to call the function win (doesn't matter which parameter). My question now is is there any way I can use that out of bounds access to call the function win since the function pointer is stored directly after the array f2 inside the struct?
of cause it can be done easily.
I show you an example code below.
I use pragma pack(1) for byte align and use print to find the address of the function, and finally I got it.
the code may can not be run on your computer.
but your can find the address by print to make bounds address equal to function address.
it may be f[0][-1] on your computer
#include <stdio.h>
typedef int (*turn_function_t)(struct board *);
#pragma pack(1)
struct board
{
turn_function_t win;
int f[10][10];
};
#pragma pack(0)
int win(struct board *b)
{
printf("Win!\n");
return 0;
}
int main()
{
struct board b;
b.win = win;
// printf("%p\n", &b.f[0][-2]);
// printf("%p\n", &b.win);
(*(turn_function_t *)(&b.f[0][-2]))(&b);
return 0;
}
does anyone know about an elegant (efficient) alternative to using large global arrays in C for an embedded system, whereby the array is written to in an interrupt service routine and it is read elsewhere asynchronously:
I have no issues with the current implementation, however I was just wondering if it is the best option.
for example:
uint8_t array_data[20] = {0};
volatile bool data_ready = false;
someIsr(void){
for(uint8_t i = 0; i < 20; i++){
array_data[i] = some_other_data[i];
}
data_ready = true;
}
main(void){
for(;;){
if(data_ready){
write_data_somewhere(&array_data[0]);
data_ready = false;
}
}
}
Thanks
Using global arrays is often the best approach unless one would need to use the storage for other purposes when the interrupt routine isn't running. An alternative is to use a global pointer to data that may be stored elsewhere, but one must be very cautious changing that pointer while interrupts are enabled.
An important caveat with your code, by the way: although the Standard regards the implications of a volatile qualifier as implementation-defined, allowing for the possibility that implementations may treat a volatile write as a potential "memory clobber", the authors of gcc require the use of compiler-specific intrinsics to prevent operations on "ordinary" objects from being reordered across operations on volatile-qualified ones.
For example, given:
volatile unsigned short out_count;
int *volatile out_ptr;
int buffer[10];
__attribute__((noinline))
void do_write(int *p, unsigned short count)
{
__asm("");
out_ptr = p;
out_count = count;
do {} while(out_count);
__asm("");
}
void test(void)
{
buffer[0] = 10;
buffer[1] = 20;
do_write(buffer, 2);
buffer[0] = 30;
buffer[1] = 40;
buffer[2] = 50;
do_write(buffer, 3);
}
because the __asm intrinsics don't use gcc-specific syntax to indicate that they might "clobber" the contents of memory in ways the compiler can't understand (even though many compilers support the use of empty __asm intrinsics for that express purpose, and such intrinsics wouldn't really serve any other purpose), and because gcc can see that there's no way that do_write could alter the contents of buffer, it "optimizes out" the code that would store the values 10 and 20 into buffer before the first call to do_write.
Clang doesn't seem quite as bad as gcc. It doesn't seem to reorder writes across volatile writes, it seems to refrain from reordering reads across functions that are not in-line expanded, and it seems to treat empty asm directives as potential memory clobbers, but I I'm not familiar enough with its documentation to know whether such restraint is by design, or merely a consequence of "missed optimizations" which might be "fixed" in future versions.
Consider using translation unit scope rather than global scope. That is declare the array static in the translation unit in which it is used. That translation unit should contain in this case the ISR that writes the data and an access function to read the data. Anything else, including main() should be in other translation units in order that that do not have direct access to the array:
#include <stdbool.h>
#include <stdint.h>
static volatile uint8_t array_data[DATA_LEN] = {0};
static volatile bool data_ready = false;
void someIsr(void)
{
for(uint8_t i = 0; i < 20; i++)
{
array_data[i] = some_other_data[i];
}
data_ready = true;
}
bool getdata( char* dest )
{
bool new_data = data_ready ;
if( data_ready )
{
memcpy( desr, array_data, sizeof(array_data) ) ;
data_ready = false ;
}
}
Then main() in some other translation unit might have:
#include "mydevice.h"
int main( void )
{
uint8_t somewhare[DATA_LEN] = {0};
for(;;)
{
if( getdata( somewhere ) )
{
// process new data
}
}
}
The above is based on your example, and the aim here is to isolate the array so that outside of the ISR the access is enforced to be read-only. In practice it is likely that you will need a "safer" data structure or access method such as a critical-section, double-buffering or a ring buffer so that the data can be accessed without risk of it being modified while it is being read.
This is no less efficient that your original global access, it is simply a restriction of the visibility and accessibility of the array.
As I mentioned in my top comment, one of best ways is to implement a ring queue.
Although I done a few ring queue implementations, here's one I just cooked up for illustration purposes. It is a [cheap] simulation of an Rx ISR for a uart [which is fairly common in embedded systems].
It is fairly complete, but I've not debugged it, so it may have some issues with the queue index calculations.
Anyway, here's the code:
// queue.c -- a ring queue
#include <stdlib.h>
#include <unistd.h>
enum {
QMAX = 1024
};
typedef unsigned char qdata_t; // queue data item
typedef struct {
int qenq; // index for enqueue
int qdeq; // index for dequeue
int qmax; // maximum number of elements in queue
int qover; // number of queue overflows
qdata_t *qbuf; // pointer to queue's buffer
} queue_t;
queue_t *rxisr_q; // pointer to Rx qeueue
// cli -- disable interrupts
void
cli(void)
{
}
// sti -- enable interrupts
void
sti(void)
{
}
// uart_ready -- uart is ready (has Rx data available)
int
uart_ready(void)
{
int rval = rand();
rval = ((rval % 100) > 95);
return rval;
}
// uart_getc -- get character from uart receiver
int
uart_getc(void)
{
int rval = rand();
rval &= 0xFF;
return rval;
}
// qwrap -- increment and wrap queue index
int
qwrap(queue_t *que,int qidx,int inc)
{
int qmax = que->qmax;
qidx += inc;
if (inc > 0) {
if (qidx >= qmax)
qidx -= qmax;
}
else {
if (qidx < 0)
qidx += qmax;
}
return qidx;
}
// qavail_total -- total amount of space available (for enqueue)
int
qavail_total(queue_t *que)
{
int qlen;
qlen = que->qdeq - que->qenq;
if (qlen < 0)
qlen += que->qmax;
qlen -= 1;
return qlen;
}
// qavail_contig -- total amount of space available (for enqueue) [contiguous]
int
qavail_contig(queue_t *que)
{
int qlen;
qlen = que->qdeq - que->qenq;
if (qlen < 0)
qlen = que->qmax - que->qenq;
qlen -= 1;
return qlen;
}
// qready_total -- total amount of space filled (for dequeue)
int
qready_total(queue_t *que)
{
int qlen;
qlen = que->qenq - que->qdeq;
if (qlen < 0)
qlen += que->qmax;
return qlen;
}
// qready_contig -- total amount of space filled (for dequeue) [contiguous]
int
qready_contig(queue_t *que)
{
int qlen;
qlen = que->qenq - que->qdeq;
if (qlen < 0)
qlen = que->qmax - que->qdeq;
return qlen;
}
// qfull -- is queue full?
int
qfull(queue_t *que)
{
int next;
next = qwrap(que,que->qenq,1);
return (next == que->qdeq);
}
// qpush -- push single value
int
qpush(queue_t *que,qdata_t chr)
{
int qenq = que->qenq;
int qnxt;
int push;
qnxt = qwrap(que,qenq,1);
push = (qnxt != que->qdeq);
if (push) {
que->qbuf[qenq] = chr;
que->qenq = qnxt;
}
return push;
}
// qalloc -- allocate a queue
queue_t *
qalloc(int qmax)
{
queue_t *que;
que = calloc(1,sizeof(*que));
que->qbuf = calloc(qmax,sizeof(qdata_t));
return que;
}
// uart_rx_isr -- ISR for uart receiver
void
uart_rx_isr(void)
{
int chr;
queue_t *que;
que = rxisr_q;
while (uart_ready()) {
chr = uart_getc();
#if 0
if (qfull(que)) {
++que->qover;
break;
}
#endif
if (! qpush(que,chr)) {
++que->qover;
break;
}
}
}
int
main(int argc,char **argv)
{
int qlen;
int qdeq;
queue_t *que;
rxisr_q = qalloc(QMAX);
que = rxisr_q;
while (1) {
cli();
qlen = qready_contig(que);
if (qlen > 0) {
qdeq = que->qdeq;
write(1,&que->qbuf[qdeq],qlen);
que->qdeq = qwrap(que,qdeq,qlen);
}
sti();
}
return 0;
}
I'm trying to write some code which would allow to render 3D graphics in console using characters and escape sequences (for color). I need it for one specific program I want to write, but, if possible, I would like to make it more universal. I'm experiencing something like screen tearing and I want to get rid of it (that the whole screen would be printed "at once"). The test is simply displaying screen filled with spaces with wite and black background (one full white frame then one full black one) in one second interval.
I have tried:
At the begging I thought about line buffering on stdout. Tried both disabling it and creating full buffor with size sufficient enough to hold every char on the screen. Second option provides better results, and by that I mean that less frames are teared, but they still are.
I thought it might be a problem with my terminal emulator (this question gave me the idea) so I started to mess around with other ones. I've got best result with Kitty but it's not there yet.
The next thing was to mess with Kitty configuration. I've noticed that if I would increase the input_delay setting to about 20 ms the problem would be almost gone. Just few of, and not every frame would be teared.
So, I came into the conclusion that in fact terminal emulators (or at least kitty) are being too fast and there might be some sort of race condition here, where buffer is not flushed yet fully and TE display both what was partially flushed and is part of old frame. Am I wrong? If not is there any way I can enforce terminals to wait for input to finnish before displaying it, or at least enforce input delay in C?
here is the relevant part of the code:
main.c
#include "TermCTRL/termCTRL.h"
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
int main()
{
termcell_t cell;
int k;
uint16_t x,y;
termCTRL_get_term_size(&x, &y);
sleep(1);
termCTRL_init();
uint8_t a = 0;
for(k=0; k<200; k++)
{
a^=255;
cell.bg.B = a;
cell.bg.G = a;
cell.bg.R = a;
cell.fg.B = a;
cell.fg.G = a;
cell.fg.R = a;
cell.symbol[0] = ' '; //symbol is in fact a string, because I want to use UTF chars too
cell.symbol[1] = '\0';
for(int xd=0; xd<x; xd++)
for(int yd=0; yd<y; yd++)
{
termCTRL_load_termcell(xd, yd, &cell);
}
termCTRL_update_screen();
sleep(1);
}
termCTRL_close();
return 0;
}
termCTRL.h
#pragma once
#include <stdint.h>
#define INPLACE_TERMCELL(FG_R, FG_G, FG_B, BG_R, BG_G, BG_B, SYMBOL) \
(termcell_t) { {FG_R, FG_G, FG_B}, {BG_R, BG_G, BG_B}, SYMBOL }
#define termCTRL_black_fill_screen() \
termCTRL_fill_screen(&INPLACE_TERMCELL(0, 0, 0, 0, 0, 0, " "))
typedef struct termcell_color_t
{
uint16_t R;
uint16_t G;
uint16_t B;
} termcell_color_t;
typedef struct termcell_t
{
termcell_color_t fg;
termcell_color_t bg;
char symbol[4];
} termcell_t;
typedef enum termCTRL_ERRNO
{
termCTRL_OUT_OF_BORDER = -2,
termCTRL_INVALID_TERMCELL = -1,
termCTRL_INTERNAL_ERROR = 0,
termCTRL_OK = 1,
} termCTRL_ERRNO;
void termCTRL_init();
void termCTRL_close();
void termCTRL_get_term_size(uint16_t *col, uint16_t *row);
termCTRL_ERRNO termCTRL_load_termcell(uint16_t x, uint16_t y, termcell_t *in);
void termCTRL_update_screen();
termCTRL_ERRNO termCTRL_fill_screen(termcell_t *cell);
termCTRL.c
#include "termCTRL.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define CONVERTED_TERMCELL_SIZE 44
#define CAST_SCREEN_TO_BUFFER \
char (*screen_buffer)[term_xsize][term_ysize][CONVERTED_TERMCELL_SIZE]; \
screen_buffer = _screen_buffer
static void *_screen_buffer = NULL;
static uint16_t term_xsize, term_ysize;
static char *IO_buff = NULL;
void termCTRL_get_term_size(uint16_t *col, uint16_t *row)
{
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
*col = w.ws_col;
*row = w.ws_row;
}
void int_decompose(uint8_t in, char *out)
{
uint8_t x = in/100;
out[0] = x + '0';
in -= x*100;
x = in/10;
out[1] = x + '0';
in -= x*10;
out[2] = in + '0';
}
termCTRL_ERRNO termCTRL_move_cursor(uint16_t x, uint16_t y)
{
char mov_str[] = "\x1b[000;000H";
if(x<term_xsize && y<term_ysize)
{
int_decompose(y, &mov_str[2]);
int_decompose(x, &mov_str[6]);
if(fputs(mov_str, stdout) == EOF) return termCTRL_INTERNAL_ERROR;
else return termCTRL_OK;
}
else
{
return termCTRL_OUT_OF_BORDER;
}
}
termCTRL_ERRNO termCTRL_load_termcell(uint16_t x, uint16_t y, termcell_t *in)
{
CAST_SCREEN_TO_BUFFER;
if(in == NULL) return termCTRL_INVALID_TERMCELL;
if(x >= term_xsize || y >= term_ysize) return termCTRL_OUT_OF_BORDER;
//because screen buffer was initialized, it is only needed to replace RGB values and symbol.
//whole escape sequence is already there
int_decompose(in->fg.R, &(*screen_buffer)[x][y][7]);
int_decompose(in->fg.G, &(*screen_buffer)[x][y][11]);
int_decompose(in->fg.B, &(*screen_buffer)[x][y][15]);
int_decompose(in->bg.R, &(*screen_buffer)[x][y][26]);
int_decompose(in->bg.G, &(*screen_buffer)[x][y][30]);
int_decompose(in->bg.B, &(*screen_buffer)[x][y][34]);
strcpy(&(*screen_buffer)[x][y][38], in->symbol); //copy symbol, note that it could be UTF char
return termCTRL_OK;
}
termCTRL_ERRNO termCTRL_fill_screen(termcell_t *cell)
{
uint16_t x, y;
termCTRL_ERRNO ret;
for(y=0; y<term_ysize; y++)
for(x=0; x<term_xsize; x++)
{
ret = termCTRL_load_termcell(x, y, cell);
if(ret != termCTRL_OK)
return ret;
}
return ret;
}
void termCTRL_update_screen()
{
uint16_t x, y;
CAST_SCREEN_TO_BUFFER;
termCTRL_move_cursor(0, 0);
for(y=0; y<term_ysize-1; y++)
{
for(x=0; x<term_xsize; x++)
fputs((*screen_buffer)[x][y], stdout);
fputs("\n", stdout);
}
//last line got special treatment because it can't have \n
for(x=0; x<term_xsize; x++)
fputs((*screen_buffer)[x][y], stdout);
fflush(stdout);
}
void termCTRL_init()
{
uint16_t x, y;
termCTRL_get_term_size(&term_xsize, &term_ysize);
IO_buff = calloc(term_xsize*term_ysize, CONVERTED_TERMCELL_SIZE);
setvbuf(stdout, IO_buff, _IOFBF, term_xsize*term_ysize*CONVERTED_TERMCELL_SIZE);
_screen_buffer = calloc(term_xsize*term_ysize, CONVERTED_TERMCELL_SIZE);
fputs("\e[?25l", stdout); //hide cursor
fputs("\x1b[2J", stdout); //clear screen
CAST_SCREEN_TO_BUFFER;
for(y=0; y<term_ysize; y++)
for (x=0; x<term_xsize; x++)
sprintf( (*screen_buffer)[x][y], "\x1b[38;2;200;200;000m\x1b[48;2;000;000;000m ");
termCTRL_update_screen();
}
void termCTRL_close()
{
free(_screen_buffer);
setvbuf(stdout, NULL, _IONBF, 0);
free(IO_buff);
printf("\e[?25h"); //show cursor
printf("\x1b[m"); //reset colors
printf("\x1b[2J"); //clear screen
}
I have a struct with variety of data types. I want to create a universal function
that can:
look through any struct and check if the item values are within
certain range for given types: (E.G. item 1 should be within 10~35,
item 3 should be either 0/1). Note that the struct's item types and
names are not passed to the function, just the struct(any struct)
Count how many items are in the struct given any structure
Example:
typedef struct _anyStruct_t
{
uint8_t item1;
uint16_t item2;
bool item3;
char item4;
}anyStruct_t
What you are asking for is effectively impossible in C.
First of all, struct types contain no metadata about their contents. At runtime, a struct object is just a sludge of bytes. There's no way to determine at runtime the number or types of members in a struct object.
Secondly, if you want to do this for any struct type, you will have to pass its address to the function as a void *, meaning you have no way of knowing whether it's a struct type at all.
You would basically have to create your own "class" type that a) stores metadata about its members and b) supports some form of inheritance such that you can pass a pointer to the base "class" type and use that to access the metadata and members.
IOW, you'd have to re-implement a good chunk of C++.
Edit
Actually, as Andrew mentions below, even C++ doesn't support reflection. You'd have to go even further.
As others have said, C doesn't support reflection and so there is no universal way to figure out what attributes exist in C data structure.
In the past I've seen folks write a meta-compiler which from some description language can be taught to generate C data structures and accessor methods.
Usually this is done if you're trying to write code that will iterate over and fill in data structures without needing to know all the details of the structures being processed - this can be useful in building messaging frameworks. But always feels cumbersome because some of your source code files are generated at build time (think lex and yacc).
Of course the other application for something like this is gdb. In that case the compiler, given '-g', generates the metadata about the data structures and embeds that in it the stabs (or gstabs, or some other) information in the object file. Your program could use /proc/self/ to find its object code on disk, open it and process through all of the stabs info. While clever, that would be very platform specific and probably pretty brittle.
look through any struct and check if the item values are within certain range for given types: (E.G. item 1 should be within 10~35, item 3 should be either 0/1). Note that the struct's item types and names are not passed to the function, just the struct(any struct)
This is not possible in C. If you only have a pointer to an unknown struct, there is no way to find out which fields the struct has.
As mentioned, one needs more information about what is in the struct. C, as opposed to C++, etc, wasn't designed around this abstraction. However, it's not impossible; nothing is stopping one from defining one's own virtual table.
#include <stdlib.h> /* EXIT rand */
#include <string.h> /* strcpy */
#include <stdio.h> /* sprintf, printf */
#include <assert.h> /* assert */
#include <stdint.h> /* (C99) uint8_t uint16_t */
#include <stdbool.h> /* (C99) bool */
union AllTypes {
bool boolean;
char letter;
uint8_t byte;
uint16_t word;
};
/* `is_valid` functions. */
static bool is_valid_boolean(const union AllTypes all) {
/* Not sure this will ever be false. */
return all.boolean == true || all.boolean == false;
}
static bool is_valid_letter(const union AllTypes all) {
return (all.letter >= 'a' && all.letter <= 'z')
|| (all.letter >= 'A' && all.letter <= 'Z');
}
static bool is_valid_byte(const union AllTypes all) {
return all.byte <= 35 && all.byte >= 10;
}
static bool is_valid_word(const union AllTypes all) {
return all.word < 1000;
}
/* `to_string` functions */
static void boolean_to_string(const union AllTypes all, char (*const a)[12]) {
strcpy(*a, all.boolean ? "true" : "false");
}
static void letter_to_string(const union AllTypes all, char (*const a)[12]) {
sprintf(*a, "'%c'", all.letter);
}
static void byte_to_string(const union AllTypes all, char (*const a)[12]) {
sprintf(*a, "b%u", all.byte);
}
static void word_to_string(const union AllTypes all, char (*const a)[12]) {
sprintf(*a, "w%u", all.word);
}
typedef void (*ToString)(const union AllTypes all, char (*const a)[12]);
/* The virtual-table. */
static const struct VTable {
ToString to_string;
bool (*is_valid)(const union AllTypes);
} vt_boolean = { &boolean_to_string, &is_valid_boolean },
vt_letter = { &letter_to_string, &is_valid_letter },
vt_byte = { &byte_to_string, &is_valid_byte },
vt_word = { &word_to_string, &is_valid_word };
/* The data has an extra `vt`; this would be implicit in C++. */
struct Data {
const struct VTable *vt;
union AllTypes all;
};
static void to_string(const struct Data *const data, char (*const a)[12]) {
data->vt->to_string(data->all, a);
}
static bool is_valid(const struct Data *const data) {
return data->vt->is_valid(data->all);
}
/* Testing. */
static void fill(struct Data *const data) {
assert(data);
switch(rand() / (RAND_MAX / 4 + 1)) {
case 0: data->vt = &vt_boolean;
data->all.boolean = rand() / (RAND_MAX / 2); break;
case 1: data->vt = &vt_letter;
data->all.letter = rand() / (RAND_MAX / 26 + 1) + 'a'; break;
case 2: data->vt = &vt_byte;
data->all.byte = rand() / (RAND_MAX / 25 + 1) + 10; break;
case 3: data->vt = &vt_word;
data->all.word = rand() / (RAND_MAX / 999 + 1); break;
}
}
int main(void) {
struct Data data[32], *d, *const d_end = data + sizeof data / sizeof *data;
char a[12];
/* Fill the data with random values. */
for(d = data; d < d_end; d++) {
fill(d);
if(!is_valid(d)) return fprintf(stderr, "Impossible!\n"), assert(0),
EXIT_FAILURE;
}
/* Print. */
fputs("{ ", stdout);
for(d = data; d < d_end; d++) {
if(d != data) fputs(", ", stdout);
to_string(d, &a);
fputs(a, stdout);
}
fputs(" }.\n", stdout);
return EXIT_SUCCESS;
}
Prints out on my machine,
{ false, w458, b15, true, b33, 'n', w34, true, b10, 'b', 'r', b33,
w526, true, 's', w761, 'b', b18, b28, w364, true, b28, b11, b32, 'l',
w477, false, 'e', 'x', w60, w504, b17 }.
Hello I am learning how to use the Uart by using interrupts in Nios and I am not sure how to start. I have made it in polling, but I am not sure how to start using interrupts.
Any help would be appreciated
Here is my code
#include <stdio.h> // for NULL
#include <sys/alt_irq.h> // for irq support function
#include "system.h" // for QSYS defines
#include "nios_std_types.h" // for standard embedded types
#define JTAG_DATA_REG_OFFSET 0
#define JTAG_CNTRL_REG_OFFSET 1
#define JTAG_UART_WSPACE_MASK 0xFFFF0000
#define JTAG_UART_RV_BIT_MASK 0x00008000
#define JTAG_UART_DATA_MASK 0x000000FF
volatile uint32* uartDataRegPtr = (uint32*)JTAG_UART_0_BASE;
volatile uint32* uartCntrlRegPtr = ((uint32*)JTAG_UART_0_BASE +
JTAG_CNTRL_REG_OFFSET);
void uart_SendByte (uint8 byte);
void uart_SendString (uint8 * msg);
//uint32 uart_checkRecvBuffer (uint8 *byte);
uint32 done = FALSE;
void uart_SendString (uint8 * msg)
{
int i = 0;
while(msg[i] != '\0')
{
uart_SendByte(msg[i]);
i++;
}
} /* uart_SendString */
void uart_SendByte (uint8 byte)
{
uint32 WSPACE_Temp = *uartCntrlRegPtr;
while((WSPACE_Temp & JTAG_UART_WSPACE_MASK) == 0 )
{
WSPACE_Temp = *uartCntrlRegPtr;
}
*uartDataRegPtr = byte;
} /* uart_SendByte */
uint32 uart_checkRecvBuffer (uint8 *byte)
{
uint32 return_value;
uint32 DataReg = *uartDataRegPtr;
*byte = (uint8)(DataReg & JTAG_UART_DATA_MASK);
return_value = DataReg & JTAG_UART_RV_BIT_MASK;
return_value = return_value >> 15;
return return_value;
} /* uart_checkRecvBuffer */
void uart_RecvBufferIsr (void* context)
{
} /* uart_RecvBufferIsr */
int main(void)
{
uint8* test_msg = (uint8*)"This is a test message.\n";
//alt_ic_isr_register ( ); // used for 2nd part when interrupts are enabled
uart_SendString (test_msg);
uart_SendString ((uint8*)"Enter a '.' to exist the program\n\n");
while (!done)
{
uint8 character_from_uart;
if (uart_checkRecvBuffer(&character_from_uart))
{
uart_SendByte(character_from_uart);
}
// do nothing
} /* while */
uart_SendString((uint8*)"\n\nDetected '.'.\n");
uart_SendString((uint8*)"Program existing....\n");
return 0;
} /* main */
I am suppose to use the uart_RecvBufferIsr instead of uart_checkRecvBuffer. How can tackle this situation?
You will need to register your interrupt handler by using alt_ic_isr_register(), which will then be called when an interrupt is raised. Details can be found (including some sample code) in this NIOS II PDF document from Altera.
As far as modifying your code to use the interrupt, here is what I would do:
Remove uart_checkRecvBuffer();
Change uart_RecvBufferIsr() to something like (sorry no compiler here so can't check syntax/functioning):
volatile uint32 recv_flag = 0;
volatile uint8 recv_char;
void uart_RecvBufferIsr(void *context)
{
uint32 DataReg = *uartDataRegPtr;
recv_char = (uint8)(DataReg & JTAG_UART_DATA_MASK);
recv_flag = (DataReg & JTAG_UART_RV_BIT_MASK) >> 15;
}
The moral of the story with the code above is that you should keep your interrupts as short as possible and let anything that is not strictly necessary to be done outside (perhaps by simplifying the logic I used with the recv_char and recv_flag).
And then change your loop to something like:
while (!done)
{
if (recv_flag)
{
uart_SendByte(recv_byte);
recv_flag = 0;
}
}
Note that there could be issues with what I've done depending on the speed of your port - if characters are received too quickly for the "while" loop above to process them, you would be losing some characters.
Finally, note that I declared some variables as "volatile" to prevent the compiler from keeping them in registers for example in the while loop.
But hopefully this will get you going.