I've read up on accessing PROGMEM for days now, and combed through several other questions, but I still can't get my code working. Any help would be appreciated.
I've included a full test sketch for Arduino below. The majority of it works, but when I loop through each byte of an "alpha" character, as pointed to by "alphabytes", I'm just getting garbage out so I'm obviously not accessing the correct memory location. The problem is, I can't figure out how to access that memory location.
I've seen several other examples of this working, but none that have different sizes of data arrays in the pointer array.
Please see line beginning with ">>>> Question is..."
// Include PROGMEM library
#include <avr/pgmspace.h>
// Variable to hold an alphabet character row
char column_byte;
// Used to hold LED pixel value during display
char led_val;
// Used to hold the screen buffer for drawing the screen
char matrix_screen[64];
/*
Define Alphabet characters. This should allow for characters of varying byte lengths.
*/
const char alpha_A[] PROGMEM = {0x06, 0x38, 0x48, 0x38, 0x06};
const char alpha_B[] PROGMEM = {0x7E, 0x52, 0x52, 0x2C};
const char alpha_C[] PROGMEM = {0x3C, 0x42, 0x42, 0x24};
/*
The "alphabytes" contains an array of references (pointers) to each character array.
Read right-to-left, alphabytes is a 3-element constant array of pointers,
which points to constant characters
*/
const char* const alphabytes[3] PROGMEM = {
alpha_A, alpha_B, alpha_C
};
/*
This array is necessary to list the number of pixel-columns used by each character.
The "sizeof" function cannot be used on the inner dimension of alphabytes directly
because it will always return the value "2". The "size_t" data
type is used because is a type suitable for representing the amount of memory
a data object requires, expressed in units of 'char'.
*/
const char alphabytes_sizes[3] PROGMEM = {
sizeof(alpha_A), sizeof(alpha_B), sizeof(alpha_C)
};
/**
* Code Setup. This runs once at the start of operation. Mandatory Arduino function
**/
void setup(){
// Include serial for debugging
Serial.begin(9600);
}
/**
* Code Loop. This runs continually after setup. Mandatory Arduino function
**/
void loop(){
// Loop through all alphabet characters
for( int a = 0; a < 3; a++) {
// Reset screen
for (int r = 0; r < 64; r++) {
matrix_screen[r] = 0;
}
// This line works to read the length of the selected "alphabyte"
int num_char_bytes = pgm_read_byte(alphabytes_sizes + a);
for (int b = 0; b < num_char_bytes; b++){
// Based on alphabytes definition,
// Examples of desired value for column_byte would be:
//
// When a=0, b=0 -> column_byte = 0x06
// When a=0, b=1 -> column_byte = 0x38
// When a=0, b=2 -> column_byte = 0x48
// When a=0, b=3 -> column_byte = 0x38
// When a=0, b=4 -> column_byte = 0x06
// When a=1, b=0 -> column_byte = 0x7E
// When a=1, b=1 -> column_byte = 0x52
// When a=1, b=2 -> column_byte = 0x52
// When a=1, b=3 -> column_byte = 0x2C
// When a=2, b=0 -> column_byte = 0x3C
// When a=2, b=1 -> column_byte = 0x42
// When a=2, b=2 -> column_byte = 0x42
// When a=2, b=3 -> column_byte = 0x24
// >>>>> Question is... how to I get that? <<<<<<<
// column_byte = pgm_read_byte(&(alphabytes[a][b])); // This doesn't work
// Thought: calculate offset each time
// int offset = 0;
// for(int c = 0; c < a; c++){
// offset += pgm_read_byte(alphabytes_sizes + c);
// }
// column_byte = pgm_read_byte(&(alphabytes[offset])); // This doesn't work
// column_byte = (char*)pgm_read_word(&alphabytes[a][b]); // Doesn't compile
column_byte = pgm_read_word(&alphabytes[a][b]); // Doesn't work
// Read each bit of column byte and save to screen buffer
for (int j = 0; j < 8; j++) {
led_val = bitRead(column_byte, 7 - j);
matrix_screen[b * 8 + j] = led_val;
}
}
// Render buffer to screen
draw_screen();
// Delay between frames
delay(5000);
}
}
/**
* Draw the screen. This doesn't have the correct orientation, but
* that's fine for the purposes of this test.
**/
void draw_screen(){
for (int a = 0; a < 8; a++) {
for (int b = 0; b < 8; b++) {
Serial.print((int) matrix_screen[a * 8 + b]);
Serial.print(" ");
}
Serial.println();
}
Serial.println();
}
Note that alphabytes it is array, which each element contains a REFERENCE (i.e. address) where corresponding characters are stored. So, you should access it in two steps.
First step is to know address in the progmem of the required item. Addresses are 16bits wide (unless you are using 128+k device).
PGM_VOID_P ptr = (PGM_VOID_P) pgm_read_word(&alphabytes[a]);
and, if you want to access it byte by byte, you can just read using this pointer, and then increment it:
for (int b = 0; b < num_char_bytes; b++) {
uint8_t column_byte = pgm_read_byte(ptr++);
...
}
After much research (and quite frankly a lot of trial and error), I have come across a solution which is working. I don't know if this the the most correct or most elegant solution, but it works.
column_byte = pgm_read_byte(pgm_read_byte(&alphabytes[a]) + b);
The inner call to pgm_read_byte():
pgm_read_byte(&alphabytes[a])
returns a value, which is the address of the character being evaluated (notice the leading "address-of" operator "&").
The outer pgm_read_byte reads that memory at an offset of "b".
This solution can also be broken down into two parts:
int memory_loc = pgm_read_byte(&alphabytes[a]);
column_byte = pgm_read_byte(memory_loc + b);
My C skills are not good enough to really explain if "memory_loc" needs to be an int (I tried it as a "char" and it also worked).
Related
What would be a way to convert an array like this
int bit_array[8] = {0,0,0,0,0,0,0,0};
into a char? (assuming bit_array is in ascii or similar)
for example an end result would preferably be like this:
int bit_array[8] = {0,1,1,0,1,0,0,0}; // h
int bit_array2[8] = {0,1,1,0,1,0,0,1}; // i
char byte;
char byte2;
byte = funny_function(bit_array);
byte2 = funny_function(bit_array2);
printf("%s%s",byte,byte2); //out: "hi"
printf("%s%s",byte,byte2); //out: "hi" will not printf anything and is wrong. %s expects a pointer to char referencing null character terminated C string and you pass integers (char is an integer).
It has to be:printf("%c%c",byte,byte2);
int funny_function(const int *bit_array)
{
int result = 0;
for(int i = 0; i < 8; i++)
{
result <<= 1;
result += !!bit_array[i];
}
return result;
}
in non zero bit_array element value is considered 1.
Without using a function call, you can do this with a loop in the body of main().
int main() {
// Only need 7 'bits'.
// Let compiler measure size.
// Use 1 byte 'char' instead of multibyte 'int'
char bits[][7] = {
{1,1,0,1,0,0,0}, // h
{1,1,0,0,1,0,1}, // e
{1,1,0,1,1,0,0}, // l
{1,1,0,1,1,0,0}, // l
{1,1,0,1,1,1,1}, // o
};
// Simply use a loop, not a function
for( int i = 0; i < sizeof bits/sizeof bits[0]; i++ ) {
char c = 0;
// 7 bit values are 'accummulated' into 'c'...
for( int ii = 0; ii < sizeof bits[0]/sizeof bits[0][0]; ii++ )
c = (char)( (c << 1) | bits[i][ii] ); // Magic happens here
putchar( c );
}
putchar( '\n' );
return 0;
}
(Friendly) output:
hello
EDIT:
As above, alternative version if output limited to only single case alphabet (fewer bits).
int main() {
// Only need 5 'bits'.
char low_bits[][5] = {
{0,1,0,0,0}, // h
{0,0,1,0,1}, // e
{0,1,1,0,0}, // l
{0,1,1,0,0}, // l
{0,1,1,1,1}, // o
};
// Simply use a loop, not a function
for( int i = 0; i < sizeof low_bits/sizeof low_bits[0]; i++ ) {
char *cp = low_bits[i]; // for clarity (brevity)
// Magic happens here...
char c = (char)(cp[0]<<4 | cp[1]<<3 | cp[2]<<2 | cp[3]<<1 | cp[4] );
putchar( c | 0x40); // uppercase. use 0x60 for all lowercase.
}
putchar( '\n' );
return 0;
}
(Not so friendly) output (unless calling to distant person):
HELLO
Assuming that you are certain that each item contains either 1 or 0, then it's as simple as this:
char funny_function (const int array[8])
{
char result = 0;
for(size_t i=0; i<8; i++)
{
result |= array[i] << (7-i);
}
return result;
}
That is:
Take the 1st array item of 0,1,1,0,1,0,0,0, left shift it 7 bits = 0x00, OR with 0x00 == 0x00.
Take the 2nd array item of 0,1,1,0,1,0,0,0, left shift it 6 bits = 0x40, OR with 0x00 == 0x40.
Take the 3rd array item of 0,1,1,0,1,0,0,0, left shift it 5 bits = 0x20, OR with 0x40 == 0x60.
And so on.
I recently got a STM8 MCU and it has the built in function LCD_GLASS_DisplayString("STRING")
The problem with that function is, as you can see below, that I cannot directly display an integer on it:
void LCD_GLASS_DisplayString(uint8_t* ptr)
{
uint8_t i = 0x01;
LCD_GLASS_Clear();
/* Send the string character by character on lCD */
while ((*ptr != 0) & (i < 8))
{
/* Display one character on LCD */
LCD_GLASS_WriteChar(ptr, FALSE, FALSE, i);
/* Point on the next character */
ptr++;
/* Increment the character counter */
i++;
}
}
How could I modify it so I could send integers directly? Also, I'm not sure I can use any libraries, so just pure C would help.
I was thinking of something like this, but it didn't work:
void LCD_GLASS_DisplayINT(uint16_t integer)
{
uint8_t i = 0x01;
LCD_GLASS_Clear();
/* Send the string character by character on lCD */
while ((integer != 0) & (i < 8))
{
/* Display one number on LCD */
LCD_GLASS_WriteChar("0" + integer%10, FALSE, FALSE, i);
/* Point on the next number*/
integer=integer/10;
/* Increment the character counter */
i++;
}
}
Any idea on how to make it work? I need to either make a function to display the integers or a way to convert them to strings before I send them over to the LCD. The code is pure C, as what I'm programming are pure drivers right now.
You're not far off with "0" + integer%10 - but you need to treat it as a character - '0' + integer%10 - and you need to pass LCD_GLASS_WriteChar a pointer to this character.
One way to do this is:
char* digits = "0123456789";
LCD_GLASS_WriteChar(&digits[integer % 10], FALSE, FALSE, i);
Also, your loop condition - while ((integer != 0) & (i < 8)) should not use bitwise and (&), but rather logical and (&&).
while ((integer != 0) && (i < 8))
You'll want to store the digits in a buffer to get the left-to-right order. On a microcontroller you'll probably want to allocate that buffer in .bss so that it doesn't take up stack. Use static to make that happen. For a 16 bit number you'll have at most 5 digits + null term, so:
static char buf[5+1] = {0};
The conversion is essentially the code you've written, except you mixed up '0' and "0":
for(uint8_t i=0; i<5; i++)
{
buf[5-i-1] = val%10 + '0';
val/=10;
}
Note that this code always leaves item buf[5] untouched and leaves a zero null terminator there.
Complete code with tests in standard C. Obviously drop puts for your custom LCD routine.
#include <stdio.h>
#include <stdint.h>
void display_int (uint16_t val)
{
static char buf[5+1] = {0};
char* p;
for(uint8_t i=0; i<5; i++)
{
buf[5-i-1] = val%10 + '0';
val/=10;
}
// trim leading zeroes
for(p=buf; *p!='\0'; p++)
{
if(*p!='0' || // stop looking at first non zero or
p[1]=='\0') // in case there is only one zero character
break;
}
puts(p); // use whatever string printing routine you got
}
int main (void)
{
display_int(0);
display_int(5);
display_int(666);
display_int(12345);
}
Division on STM8 is very expensive. We can optimize the code a bit by not filling up the whole buffer if we don't have to. This saves us several DIV calls. Optimized version, faster but harder to read:
void display_int (uint16_t val)
{
static char buf[5+1] = {0};
char* p;
char* start;
for(uint8_t i=0;;i++)
{
buf[5-i-1] = val%10 + '0';
val/=10;
if(val==0)
{
start = &buf[5-i-1];
break;
}
}
// trim leading zeroes
for(p=start; *p!='\0'; p++)
{
if(*p!='0' || // stop looking at first non zero or
p[1]=='\0') // in case there is only one zero character
break;
}
puts(p); // use whatever string printing routine you got
}
So I'm building a disassembler that will convert a file containing hexadecimal data into assembly language.
So from this format I could convert the hexadecimal data in the file into decimal using uint8_t and store them in an array. Then I decided to bit shift the last number in the array to get number of instructions of the last function; essentially I'm parsing backwards since I don't know how much padding there are at the beginning and the number of ops in a function is given at the end of the function. But then I realised that the operations varies in bit size and aren't in perfect 8 or 16 bit bounds. So then I was stuck since my array, using the example at the top, was essentially this:
uint8_t hex[] = {0x00, 0x03, 0x02, 0x01, 0x42, 0x82, 0x86, 0x04, 0x10, 0x45};
So can anyone help me with the logic in parsing? This is my first time posting so I'm sorry if I'm missing anything and will provide more information or delete if needed
Instead of shifting and masking (which I think would be really complicated) what if you convert the uint8_t array into an array of bits - it uses a lot more memory but you can access individual bits much easier.
Here is a sample program that does this:
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
uint8_t getBits(uint8_t *bits, uint8_t size, uint32_t *index)
{
uint8_t value = 0;
*index -= size; // decrement index to the starting point
for(uint32_t i=0; i<size; i++)
value = (value<<1) | bits[*index+i];
return value;
}
int main()
{
// sample program
uint8_t array[] = {0x00,0x03,0x02,0x01,0x42,0x82,0x86,0x04,0x10,0x45};
// program with zero padding
// uint8_t array[] = {0xE8,0x39,0x06,0xA0,0xC4,0x16,0x82,0x90,0x4A,0x08,0x41};
uint32_t array_size = sizeof(array)/sizeof(*array); // 10 bytes
uint32_t bits_size = 8*array_size; // 80 bytes
uint8_t* bits = malloc(bits_size);
for(uint32_t a=0;a<array_size;a++)
for(uint32_t b=0;b<8;b++)
bits[a*8+b] = (array[a] >> (7-b)) & 1;
puts("Binary program file:");
for(uint32_t i=0;i<bits_size;i++)
printf("%s%d",(i%8?"":" "),bits[i]);
puts("");
enum { MOV, CAL, RET, REF, ADD, PRINT, NOT, EQU};
uint8_t params[] = { 2, 1, 0, 2, 2, 1, 1, 1};
const char *opcodes[] = {"MOV","CAL","RET","REF","ADD","PRINT","NOT","EQU"};
enum { VAL, REG, STK, PTR};
uint8_t value_size[] = { 8, 3, 5, 5};
const char *types[] = {"VAL","REG","STK","PTR"};
uint32_t index = bits_size; // start at end
// minimum program size is function(3) + opcode(3) + size(5)
// if there are less than that number of bits then it must be padding
while(index>10)
{
uint8_t size = getBits(bits,5,&index);
printf("\nsize=%d\n",size);
if (size > 0)
{
for(int o=0; o<size; o++)
{
uint8_t opcode = getBits(bits,3,&index);
printf("opcode=%s",opcodes[opcode]);
for(int p=0; p<params[opcode]; p++)
{
printf("%c ",p?',':':');
uint8_t type = getBits(bits,2,&index);
printf("type=%s ",types[type]);
uint8_t value = getBits(bits,value_size[type],&index);
printf("value=%d",value);
}
puts("");
}
uint8_t function = getBits(bits,3,&index);
printf("function=%d\n",function);
}
}
return 0;
}
Try it at https://onlinegdb.com/S1qVStz8d
How it getBits() works:
You make an array of individual digits from the original value, and then you take bits from it one at a time to make a new value - getBits() is the function I have written for that.
To understand how it works imagine how it works in base 10: 321 is put into the array {3,2,1} and you could turn it back into a value with:
value = 0;
value = value*10 + digits[0];
value = value*10 + digits[1];
value = value*10 + digits[2];
Which gives (((0)*10+3)*10+2)*10+1 which is 321
If 5 (binary 101) is put into the array {1,0,1}, you could turn it back into a value with:
value = 0;
value = value*2 + bits[0];
value = value*2 + bits[1];
value = value*2 + bits[2];
Which gives (((0)*2+1)*2+0)*2+1 which is 5 (binary 101)
And that does work. And a decent compiler would optimize the *2 into <<1 and the + into |, but you could do it yourself (which is what I did):
value = 0;
value = (value<<1) | bits[0];
value = (value<<1) | bits[1];
value = (value<<1) | bits[2];
Which produces that same binary 00000101
It's just a readability thing - with decimal you expect to see value*10+x but with binary you expect to see bit operations like shift/or instead of math operations like multiply/add.
Then, if you use a loop with a size and an index that points to the end of the array, you get:
uint8_t value = 0;
index -= size; // decrement index to the starting point
for(uint32_t i=0; i<size; i++)
value = (value<<1) | bits[index+i];
But, of course, if it is a function then index needs to be a pointer and you need to dereference it everywhere:
uint8_t getBits(uint8_t *bits, uint8_t size, uint32_t *index)
{
uint8_t value = 0;
*index -= size; // decrement index to the starting point
for(uint32_t i=0; i<size; i++)
value = (value<<1) | bits[*index+i];
return value;
}
I tried to write a PIC program with C and what it does is turn on a series of 8 LED's (like Knight Rider LED illumination :D ). I have created the circuit design and tested with a simple c program that sets the state of the lights and it works. Now I want to streamline my code.
So i have created 2 functions for delaying and getting the required HEX value of the LED. the 2 methods are like this.
#define MAX 8
#define LEFT 1
#define RIGHT 2
#define BOTH 0
void delay_ms(int ms) {
while(ms > 0)
ms--;
}
int getHex(int delay, int dir, int *pin) {
int hex[] = {0x01, 0x02, 0x04, 0x10, 0x20, 0x40, 0x80};
if (dir == RIGHT) {
for (int i = 0; i < MAX; i++)
{
*pin = hex[i];
delay_ms(delay);
}
} else if( dir == LEFT ) {
for (int i = MAX - 1; i == 0; i--)
{
pin = hex[i];
delay_ms(delay);
}
}
}
and i have this in the main() function
main() {
TRISA = 1;
TRISB = 0;
while(1) {
if(RA0 == 0)
getHex(5000, RIGHT, PORTB);
}
}
What im trying to do is pass the PORTB predefined variable as a pointer to the function so it is set with the proper hex value. But i get the following warnings when i compile with the MPLAB IDE,
Warning [357] D:\...\main.c; 24.13 illegal conversion of integer to pointer
Warning [357] D:\...\main.c; 37.22 illegal conversion of integer to pointer
and when the program hex is added and run in the Proteus 8 nothing happens and the following warning appears.
[PIC16 MEMORY]PC=0x03AF. Attempt to write unimplemented memory location 0x0087 with 0x01 ignored
[PIC16 MEMORY]PC=0x03AF. Attempt to write unimplemented memory location 0x0087 with 0x02 ignored
[PIC16 MEMORY]PC=0x03AF. Attempt to write unimplemented memory location 0x0087 with 0x04 ignored
the final Hex value in the error correspond with the hex value i am trying to set as the value of PORTB. What am i doing wrong.. Please help.
There are several ways that such pre-defined registers may be declared. I don't know how Mplab does it, but the most common way is this:
#define PORTB (*(volatile uint8_t*)0x1234)
where 0x1234 is the hardware address of that register. This macro accesses the register directly, but the * to the left makes it so that you can use the macro as if PORTB was an ordinary variable and not a pointer.
If this is the case, then you need to pass &PORTB to your function that expects a pointer.
Changed the getHex Method definition to this.
int getHex(int delay, int dir, int *pin) {
int hex[] = {0x01, 0x02, 0x04, 0x10, 0x20, 0x40, 0x80};
if (dir == RIGHT) {
for (int i = 0; i < MAX; i++)
{
*pin = hex[i];
delay_ms(delay);
}
} else if( dir == LEFT ) {
for (int i = MAX - 1; i == 0; i--)
{
*pin = hex[i];
delay_ms(delay);
}
}
}
and then called the function with the following..
getHex(2000, RIGHT, &PORTB);
I want to extend the u-boot SPL code with some fuzzy extractor logic by adding code into {u-boot_sources}/arch/arm/cpu/armv7/omap-common/hwinit-common.c. U-boot shall be used on a PandaBoard ES (omap4460 SoC).
Thus, first I successfully implemented the code on my x86 pc and I am porting it to the ARM-based PandaBoard. The complete code can be found here (as a side note the "main" function is s_init()):
http://pastebin.com/iaz13Yn9
However, I am expecting dozens of unexptected effects, which results in either stopping during the execution of the code, stopping u-boot after reading u-boot.img or not sending output (and thus not booting) at all.
For example, I want to call two functions (computeSyndrome, decodeErrors) inside a for-loop, which is part of another function golayDecode.
For my first problem please ignore the code below the multiline comment starting with /* >>>> These lines of code below totally break u-boot. Also only the function computeSyndrome in conjunction with the calling function golayDecode is important.
The issue: If comment out both functions computeSyndrome and decodeErrors everything works fine and the OS (Android) is booting. However, if computeSyndrome is not commented out and thus gets processed, u-boot stucks after displaying reading u-boot.img.
The funny thing about it: even if I replace computeSyndrome with a bogus function which does not but iterating a values or displaying stuff, u-boot stucks as well.
Furthermore, if I remove the multiline comment furhter below to also include the residual code, u-boot doesn't display ony character. (1*)
I am a beginner regarding microprocessor programming but I can not figure out a possible error in these 12 lines of the computeSyndrome function or the general behaviour of u-boot at all. (2*)
Does anyone have a clue what I am missing?
Thanks,
P.
1* I am using minicom to display the output of u-boot, which I receive over serial-usb-converter.
2* I am using the following compiler flags to make sure there are no errors at compile time: -Wall -Wstrict-prototypes -Wdisabled-optimization -W -pedantic
void golayDecode(volatile int x[12], volatile int y[12], volatile unsigned int golayEncodedSecret[30], volatile unsigned int s, volatile unsigned char repetitionDecodedSecretBits[360]){
printf("\n[I] - Performing Golay decoding\r\n");
volatile unsigned char secret[22] = {0};
volatile unsigned char currentByte = 0, tmpByte = 0;
volatile unsigned int golayDecodedSecret[30] ={0};
volatile int twelveBitCounter = 0;//, j = 0, k = 0, q = 0, aux = 0, found = 0, bitCounter = 0, i_2 = 7, currentSecretEncByte = 0x00;
volatile int c_hat[2] = {0}, e[2] = {0};
e[0] = s;
e[1] = 0;
for(twelveBitCounter = 0; twelveBitCounter < 30; twelveBitCounter+=2){
printf("Computing syndrome and decoding errors for bytes %03x & %03x\n", golayEncodedSecret[twelveBitCounter], golayEncodedSecret[twelveBitCounter+1]);
computeSyndrome(golayEncodedSecret[twelveBitCounter], golayEncodedSecret[twelveBitCounter+1], x, y, s);
decodeErrors(golayEncodedSecret[i], golayEncodedSecret[i+1], x, y, s);
}
printf("\n[D] - Reconstructing secret bytes\r\n");
/* >>>> These lines of code below totally break u-boot
for(i = 0; i < 30; i+=2){
currentSecretEncByte = golayDecodedSecret[i];
volatile int j = 11;
// Access each source bit
for(; 0<=j; j--){
volatile int currentSourceBit = (currentSecretEncByte >> j) & 0x01;
repetitionDecodedSecretBits[bitCounter] = currentSourceBit;
bitCounter++;
}
}
k = 0;
for(i = 0; i<176; i++){
tmpByte = repetitionDecodedSecretBits[i] << i_2;
currentByte = currentByte | tmpByte;
i_2--;
if(i_2==0){ // We collected 8 bits and created a byte
secret[k] = currentByte;
i_2 = 7;
tmpByte = 0x00;
currentByte = 0x00;
k++;
}
}
SHA256_CTX ctx;
unsigned char hash[32];
printf("\n[I] - Generating secret key K\n");
sha256_init(&ctx);
sha256_update(&ctx,secret,strlen((const char*)secret));
sha256_final(&ctx,hash);
printf("\n[I] - This is our secret key K\n\t==================================\n\t");
print_hash(hash);
printf("\t==================================\n");
*/
}
/* Function for syndrome computation */
void computeSyndrome(int r0, int r1, volatile int x[12], volatile int y[12], volatile unsigned int s){
unsigned int syndromeBitCounter, syndromeMatrixCounter, syndromeAux;
s = 0;
for(syndromeMatrixCounter=0; syndromeMatrixCounter<12; syndromeMatrixCounter++){
syndromeAux = 0;
for(syndromeBitCounter=0; syndromeBitCounter<12; syndromeBitCounter++){
syndromeAux = syndromeAux^((x[syndromeMatrixCounter]&r0)>>syndromeBitCounter &0x01);
}
for(syndromeBitCounter=0; syndromeBitCounter<12; syndromeBitCounter++){
syndromeAux = syndromeAux^((y[syndromeMatrixCounter]&r1)>>syndromeBitCounter &0x01);
}
s = (s<<1)^syndromeAux;
}
}
/* Funcion to recover original byte */
void decodeErrors(int r0, int r1, volatile int x[12], volatile int y[12], volatile unsigned int s){
//printf("\n[D] - Starting to decode errors for %3x | %3x\n", r0, r1);
volatile unsigned int c_hat[2] = {0xaa}, e[2] = {0xaa};
volatile unsigned int q;
unsigned int i, j, aux, found;
//printf("Step 2\n");
if(weight(s)<=3){
e[0] = s;
e[1] = 0;
}else{
/******* STEP 3 */
//printf("Step 3\n");
i = 0;
found = 0;
do{
if (weight(s^y[i]) <=2){
e[0] = s^y[i];
e[1] = x[i];
found = 1;
printf("\ntest 2\n");
}
i++;
}while ((i<12) && (!found));
if (( i==12 ) && (!found)){
/******* STEP 4 */
//printf("Step 4\n");
q = 0;
for (j=0; j<12; j++){
aux = 0;
for (i=0; i<12; i++)
aux = aux ^ ( (y[j]&s)>>i & 0x01 );
q = (q<<1) ^ aux;
}
/******* STEP 5 */
//printf("Step 5\n");
if (weight(q) <=3){
e[0] = 0;
e[1] = q;
}else{
/******* STEP 6 */
//printf("Step 6\n");
i = 0;
found = 0;
do{
if (weight(q^y[i]) <=2){
e[0] = x[i];
e[1] = q^y[i];
found = 1;
}
i++;
}while((i<12) && (!found));
if ((i==12) && (!found)){
/******* STEP 7 */
printf("\n[E] - uncorrectable error pattern! (%3x | %3x)\n", r0, r1);
/* You can raise a flag here, or output the vector as is */
//exit(1);
}
}
}
}
c_hat[0] = r0^e[0];
c_hat[1] = r1^e[1];
//printf("\t\tEstimated codeword = %x%x\n", c_hat[0], c_hat[1]);
}
Indeed, the code was a little bit too complex to be executed at this point of boot time. At this time there is ne real CRT and I only have a minimal stack.
Thus, I moved the code to board_init_f() which is still part of the SPL. It gave more stable results and my algorithm now works as expected.