pointer arithmetic gone mad

Go To Last Post
12 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Guys, I have a f_seek function I'm working on.  I have listed the code below.  In the test (cluster size equals 4096) I open the file and the pointer points to the first data element.   I then f_seek, 5000 offset from the current position.  The f_seek function then correctly detects that a cluster move to the next position is required.  So it removes 4096 and moves to the next cluster.  It then offsets by 904, also correct.  BUT!

 

When it goes to do the following to the pointer, it is incorrectly offset.  I hope I've explained this has best I can.

			c_printf("\n\r[r]Offset %i", iOffset);
			c_printf("\n\r[m]Current Ptr Addr! %x", file->data_file->data_cache);

			// update_data_cache data pointer to new location
			file->data_file->data_cache += iOffset;


			c_printf("\n\r[m]New Ptr Addr! %x", file->data_file->data_cache);

Also, if instead I do an offset of 3000, i.e less than the cluster size the math works?  I did suspects a failure to allocate memory or something but I've checked everything.

 

FULL CODE

/*
 * fat32_seek.c
 *
 *  Created on: 8 Apr 2022
 *      Author: wmjen
 */


/*
 * exfat_seek.c
 *
 *  Created on: 8 Dec 2021
 *      Author: wmjen
 */
#include <stdio.h>
#include <stdlib.h>

#include "fat32_seek.h"
#include "clusters_fat32.h"
#include "fat32.h"


#include "../../rtx/system_malloc.h"

#include "../hal/file_system_driver.h"
#include "../../tx/user_interface/console.h"
/**
 *
 * @param file - file stream pointer
 * @return	new cluster number
 *
 * Add data cluster to data cluster chain
 */
static unsigned int data_table_remove_cluster(FILEX * file){

	// remove this directory
	struct data_file_entry * dir = file->data_file->data_file_table->cluster_chain->prev;

	if( file->data_file->data_file_table->nr == 1){
		file->data_file->data_file_table->nr = 0;
	}
	else
	{
		file->data_file->data_file_table->nr--;

		if(file->data_file->data_file_table->cluster_chain == dir){
			file->data_file->data_file_table->cluster_chain = dir->next;
		}

		dir->prev->next = dir->next;
		dir->next->prev = dir->prev;
	}

	// free memory
	rtos_free(dir);
	return(1);
}

void fat32_close_indexing(FILEX * file){

	while(file->data_file->data_file_table->nr != 0){
		data_table_remove_cluster(file);
	}
}

/**
 *
 * @param file stream pointer
 * @return ignore
 */
static unsigned int data_table_insert_cluster(FILEX * file){

	// allocate memory for new link node
	struct data_file_entry * dir = rtos_malloc(sizeof(struct data_file_entry));

	// log cluster number
	dir->cluster_nr = file->data_file->data_cluster_nr;


	// add to double link list
	if( file->data_file->data_file_table->nr == 0){

		// setup ptrs for quick access
		file->data_file->data_file_table->start 	= dir;
		file->data_file->data_file_table->end 		= dir;
		file->data_file->data_file_table->position 	= dir;


		file->data_file->data_file_table->cluster_chain 	= dir;
		dir->next											= dir;
		dir->prev											= dir;
		file->data_file->data_file_table->nr				= 1;
	}
	else{
		file->data_file->data_file_table->nr++;

		dir->next = file->data_file->data_file_table->cluster_chain;
		dir->prev = file->data_file->data_file_table->cluster_chain->prev;

		file->data_file->data_file_table->cluster_chain->prev->next = dir;
		file->data_file->data_file_table->cluster_chain->prev = dir;

		file->data_file->data_file_table->end = dir;
	}
	return 1;
}


/**
 *
 * @param file stream pointer
 * @return last cluster number
 */
void fat32_build_file(FILEX * file){

	unsigned int cluster, temp;

	cluster = get_cluster_marker(file, file->data_file->data_cluster_nr);
	temp = file->data_file->data_cluster_nr;

	// traverse the cluster chain until we reach a end msarker, i.e 0xffffffff
	while(1){


		// insert cluster on to link list
		data_table_insert_cluster(file);

		// quit when we reach end cluster
		if(cluster >= 0x0ffffff8)
			break;

		// setup new cluster
		file->data_file->data_cluster_nr = cluster;
		cluster = get_cluster_marker(file, file->data_file->data_cluster_nr);
	}

	// restore pointer to first cluster
	file->data_file->data_cluster_nr = temp;
}


static char load_first_cluster_index(FILEX * file){

	if(file->data_file->data_file_table->nr > 0){

		// obtain start cluster
		unsigned int cluster_nr = file->data_file->data_file_table->start->cluster_nr;

		// point position to start
		file->data_file->data_file_table->position = file->data_file->data_file_table->start;

		// obtain relative hardware address
		unsigned int hardware_addr = cluster_address(file, cluster_nr);

		// setup clusters
		file->data_file->data_cluster_nr = cluster_nr;
		file->data_file->data_cluster_addr = hardware_addr;

		// reset data read ptr
		file->data_file->data_cache = file->data_file->free_data;
		return cluster_nr;
	}
	return 0;
}


static char load_end_cluster_index(FILEX * file){

	if(file->data_file->data_file_table->nr > 0){

		// obtain end position cluster
		unsigned int cluster_nr = file->data_file->data_file_table->end->cluster_nr;

		// set position to the end
		file->data_file->data_file_table->position = file->data_file->data_file_table->end;

		// obtain relative hardware address
		unsigned int hardware_addr = cluster_address(file, cluster_nr);

		// setup clusters
		file->data_file->data_cluster_nr = cluster_nr;
		file->data_file->data_cluster_addr = hardware_addr;

		// reset data read ptr
		file->data_file->data_cache = file->data_file->free_data;
		return cluster_nr;
	}
	return 0;
}



static char load_next_cluster_index(FILEX * file){

	if(file->data_file->data_file_table->nr > 0){

		// obtain next cluster
		unsigned int cluster_nr = file->data_file->data_file_table->position->next->cluster_nr;

		// set position to next cluster position
		file->data_file->data_file_table->position = file->data_file->data_file_table->position->next;

		// obtain relative hardware address
		unsigned int hardware_addr = cluster_address(file, cluster_nr);

		// setup clusters
		file->data_file->data_cluster_nr = cluster_nr;
		file->data_file->data_cluster_addr = hardware_addr;

		// reset data read ptr
		file->data_file->data_cache = file->data_file->free_data;
		return cluster_nr;
	}
	return 0;
}


static char load_prev_cluster_index(FILEX * file){

	if(file->data_file->data_file_table->nr > 0){

		// obtain previous cluster
		unsigned int cluster_nr = file->data_file->data_file_table->position->prev->cluster_nr;

		// set position to previous cluster
		file->data_file->data_file_table->position = file->data_file->data_file_table->position->prev;

		// obtain relative hardware address
		unsigned int hardware_addr = cluster_address(file, cluster_nr);

		file->data_file->data_cluster_nr = cluster_nr;
		file->data_file->data_cluster_addr = hardware_addr;

		// reset data read ptr
		file->data_file->data_cache = file->data_file->free_data;
		return cluster_nr;
	}
	return 0;
}


/**
 *
 * @param file - file Stream
 * @param iOffset - offset from location specified
 * @param iWhence - SET, CUR, END locations
 */
unsigned long long fat32_seek(FILEX * file, int iOffset, int iWhence ){

	int cluster_count;
	char update_data_cache = 0;


	/**
	 * Handle SEEK, i.e. move forward/backwards through the file!!!
	 */
	if(iWhence == FF_SEEK_SET){

		// configure f_tell
		file->data_file->f_tell_index = iOffset;

		// load first cluster if we are not already pointing to it
		if(file->data_file->data_file_table->start !=  file->data_file->data_file_table->position){

			// load first cluster
			load_first_cluster_index(file);

			// update data cache
			update_data_cache = 1;
		}


		// if offset is greater than zero
		if(iOffset > 0){

			// if need to load one or more clusters due to the offset being greater than
			// the cluster size
			if(iOffset >= fat_cluster_size(file)){

				// number of clusters to traverse
				cluster_count = iOffset / fat_cluster_size(file);

				for(int i = 0; i < cluster_count; i++){

					// move to next cluster position
					load_next_cluster_index(file);
				}

				// update data cache
				update_data_cache = 1;
			}


			// calculate offset required, mod
			iOffset = iOffset % fat_cluster_size(file);

			// update_data_cache ptr
			file->data_file->data_cache = file->data_file->free_data + iOffset;
		}
		else
			file->data_file->data_cache = file->data_file->free_data;
	}

	else if(iWhence == FF_SEEK_END){

		// go to end cluster position if we are elsewhere
		if(file->data_file->data_file_table->end != file->data_file->data_file_table->position){

			// load end cluster
			load_end_cluster_index(file);

			// update data cache
			update_data_cache = 1;

			// go to last element in file
			file->data_file->data_cache = file->data_file->free_data + (file->data_file->file_size % (fat_cluster_size(file) - 1));
		}



		// if offset requires processing then begin by calculating the offset in clusters required
		if(iOffset < 0){

			// f_tell information
			file->data_file->f_tell_index = file->data_file->file_size - iOffset;

			// make positive
			iOffset = iOffset * -1;

			// if boundary violated then handle
			if(((file->data_file->data_cache - file->data_file->free_data) - iOffset) < 0){

				// subtract boundary
				iOffset -= (file->data_file->data_cache - file->data_file->free_data);

				// point to previous cluster
				load_prev_cluster_index(file);

				// go to last element in file
				file->data_file->data_cache = file->data_file->free_data + (fat_cluster_size(file) - 1);

				// update data cache
				update_data_cache = 1;
			}

			// if offset is now still greater than a cluster size then handle
			if(iOffset >= fat_cluster_size(file)){

				// update data cache
				update_data_cache = 1;

				// number of clusters to travel
				cluster_count = iOffset / fat_cluster_size(file);

				// begin travelling backwards
				for(int i = 0; i < cluster_count; i++)
					load_prev_cluster_index(file);

				// go to last element in file
				file->data_file->data_cache = file->data_file->free_data + (fat_cluster_size(file) - 1);
			}

			// calculate offset modula operator
			iOffset = iOffset % fat_cluster_size(file);

			// update_data_cache ptr
			file->data_file->data_cache -= iOffset;
		}
	}


	else if(iWhence == FF_SEEK_CUR){

		// handle overflow
		if(iOffset > 0){

			// f_tell information
			file->data_file->f_tell_index += iOffset;

			// handle overflow first - boundary
			if(((file->data_file->data_cache - file->data_file->free_data) + iOffset) >= fat_cluster_size(file)){

				// calculate new offset by removing the offset required to reach next cluster
				iOffset -= (fat_cluster_size(file) - (file->data_file->data_cache - file->data_file->free_data));

				// update data cache
				update_data_cache = 1;

				// load next cluster
				load_next_cluster_index(file);
			}

			// if offset is still passing a cluster boundary
			if(iOffset >= fat_cluster_size(file)){

				// update data cache
				update_data_cache = 1;

				// number of clusters to traverse
				cluster_count = iOffset / fat_cluster_size(file);

				// traverse clusters
				for(int i = 0; i < cluster_count; i++)
					load_next_cluster_index(file);
			}


			//calculate offset remaining
			iOffset = iOffset % fat_cluster_size(file);


			c_printf("\n\r[r]Offset %i", iOffset);
			c_printf("\n\r[m]Current Ptr Addr! %x", file->data_file->data_cache);

			// update_data_cache data pointer to new location
			file->data_file->data_cache += iOffset;


			c_printf("\n\r[m]New Ptr Addr! %x", file->data_file->data_cache);

		}
		else{

			// make positive
			iOffset = iOffset * -1;

			// f_tell information
			file->data_file->f_tell_index -= iOffset;

			// will a boundary be violated?
			if(((file->data_file->data_cache - file->data_file->free_data) - iOffset) < 0){

				// remove boundary
				iOffset -= (file->data_file->data_cache - file->data_file->free_data);

				// update data cache
				update_data_cache = 1;

				// move to previous cluster
				load_prev_cluster_index(file);

				// go to last element in file
				file->data_file->data_cache = file->data_file->free_data + (fat_cluster_size(file) - 1);
			}

			// offset still violates the boundary
			if(iOffset >= fat_cluster_size(file)){

				// update data cache
				update_data_cache = 1;

				// number of clusters to travel
				cluster_count = iOffset / fat_cluster_size(file);

				// begin travelling backwards
				for(int i = 0; i < cluster_count; i++)
					load_prev_cluster_index(file);

				// go to last element in file
				file->data_file->data_cache = file->data_file->free_data + (fat_cluster_size(file) - 1);
			}

			// calculate offset mod
			iOffset = iOffset % fat_cluster_size(file);

			// set the new data pointer offset
			// update_data_cache memory
			file->data_file->data_cache -= iOffset;
		}
	}

	// update_data_cache data cache with new cluster
	if(update_data_cache)
		dma_hardware_read(1, file->data_file->data_cluster_addr, fat_sectors_per_cluster(file), file->data_file->free_data, 0);

	return -1;
}


 

Last Edited: Fri. Apr 15, 2022 - 01:05 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Fianawarrior wrote:
Guys, I have a f_seek function I'm working on. 

 

So, where is that `f_seek` function? What does the provided wall of code have to do with that function? I don't see any mentions of `f_seek` there.

 

Fianawarrior wrote:
When it goes to do the following to the pointer, it is incorrectly offset.  I hope I've explained this has best I can.

 

"Incorrectly offset" is not an explanation at all. It is the same as "my program doesn't work" - a meaningless combination of words.

 

What exactly happened? What's incorrect? An example of incorrect value, perhaps?

 

Fianawarrior wrote:

file->data_file->data_cache += iOffset;

 

Where in the code did you provide the declaration of `data_cache` field? What is the type of `data_cache`? Where can we see it?

 

You are asking a question about "pointer arithmetic" (supposedly) on `data_cache` (supposedly), yet you provide no information on what `data_cache` is. Is this even a pointer? And if it is, what is the type of that pointer?

 

I would like to see a detailed explanation (1-2 pages) about why you are dumping heaps of irrelevant code/text into the forum, yet you don't even bother to provide the most basic and most obviously necessary data. Are you just trying to flood the forum or what? Sit down, write that explanation and post it here. Now.

 

 

 

 

 

 

Dessine-moi un mouton

Last Edited: Thu. Apr 14, 2022 - 05:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Fianawarrior wrote:
FULL CODE

Oh no it isn't:

#include "fat32_seek.h"
#include "clusters_fat32.h"
#include "fat32.h"

#include "../../rtx/system_malloc.h"

#include "../hal/file_system_driver.h"
#include "../../tx/user_interface/console.h"

There's too much code to read, so I tried unsuccessfully to reproduce your test.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
file->data_file->data_cache

Is a pointer to type unsigned char. I tried not calling the 

load_next_cluster_index(file);

to see it it was trampling on any data but that failed to yield any results.  I've watch the pointer value before the address addition and after and the result is wrong.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What is the target MCU make and model of this exercise?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AVR UC3 and ARM Cortex-A5, aka "The Beast".  

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As I suspected:. Moderators, please move or remove.  Please chastise this member for this same repeated sin.  Do I need to call the parents?  Err, I mean report the thread?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is the UC3 AVR not AVR enough.  

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So the question is:Where do we move it to? UC3 or ARM  forum???frown or simply let it die here of natural causes?

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AndreyT wrote:
Sit down, write that explanation and post it here. Now.

 

Annnnnnnd what will happen if he does not?

 

 

theusch wrote:
As I suspected:. Moderators, please move or remove.  Please chastise this member for this same repeated sin.  Do I need to call the parents?  Err, I mean report the thread?

 

Nope.  PM has been sent.

 

 

js wrote:
So the question is:Where do we move it to? UC3 or ARM  forum???frown or simply let it die here of natural causes?

 

As my PM mentioned, the UC3 is a series that never really took off, and the plane is still sitting on the tarmac idling till it finally runs out of gas.  Therefore thread shall be moved to the programming forum in the ARM section....where it can hppen however it wants to happen.

 

Cheerio!

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

js wrote:
or simply let it die here of natural causes?

Notice how carefully OP refrained from giving the information, as it is known that I will object each time.

 

As I've responded often [references upon request] OP and others post here as there is activity, and the experts fall over themselves to work on the situation.  Every time the kid throws a tantrum, give him another ice cream.

 

jgmdesign wrote:

Where do we move it to? UC3 or ARM  forum???

I've also gone back and quoted the Forum tree.  I know that ARM isn't in the same tree as this forum.  UC3?  Why do I suspect that OP only mentioned that to deflect?  But that works, as this would be the correct place for UC3.  Let's see a picture of that board under test, and then I can

 

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Fri. Apr 15, 2022 - 01:34 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My mum always said, "if you can't say anything nice then don't say anything". I was not deflecting by mentioning UC3, I have a number of development boards made by a friend in Germany.  I promise to behave in the AVR8 bit forum.  I'll post some examples tomorrow showing the error occurring tomorrow, it's late here.

 

Wm.