Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12595 Discussions

peripheral I/O transfer using unconventional data types

Honored Contributor II



This thread picks up from a previously posted one, here ( I began a new thread, as the previous one had gotten a bit off topic. 


While I've already been given some very good suggestions, I'm still a little confused on transfer to and from peripherals, when unconventional data types are being used, i.e. ones which aren't necessarily base 2 and at least 8 bits in size. 


I have a large number of hardware components which I need to transfer data to, which are using values that are sometimes 3 bits in length, sometimes 7 bits, etc. I understand that bit fields are simply a poor option in the case of memory to peripheral transfers and, in general, are hardly suggested in any case due to portability issues. Per previous suggestions, defining macros for addressing the peripheral looks to be a good option for bypassing the HAL API and caching, when using the ldwio and stwio instructions. 


The previous thread pretty much answered the question of peripheral interface, so it looks like the problem is isolated to the application layer and how the data can be formatted in memory. I know that compiler optimization can be taken out of the equation, to some extent, using objects defined by the pre-processor, but it seems like inevitably, there's going to be some interaction with a data structure which is going to need bit field members and is going to be compiled.  


Because of the way the peripherals have been designed, it seems like I don't really have an option to include portability, but suggestions otherwise would be greatly appreciated.
0 Kudos
1 Reply
Honored Contributor II

Alright, maybe I'll try the Socratic method :) 


There's a defined base address in the BSP system.h file, which I'll call BASE as an example. Because it's a volatile address, I'll call a pointer in a macro or as a const, like this, 


#define PerBase ((uint32_t volatile *)BASE) 


uint32_t volatile *const per_base = (uint32_t *) BASE; 

In either case, we have a pointer to a volatile unsigned int at the peripherals base address. The base address can now be accessed like this, 

uint32_t data; *per_base = data; /* write to peripheral*/ data = *per_base; /* read from peripheral*/  


Based on the previous advice, this looks like a good method for providing un-cached I/O access to the registers and please correct me if I'm wrong. However, I'm still stuck on how to implement a portable solution for copying the data from bit-fields to an unsigned int. I understand that a union of the bit-field struct type and uint32_t can be used,  

union reg { struct fields { uint32_t data0 : 12; uint32_t data1 : 1; ... }; uint32_t all_data; }; 

but that doesn't eliminate the bit-field problems with regards to portability. 


An options which I did think about, but I'm not quite sure will work, is to create a structure similar to the bit-field one, but without breaking apart the members and just keeping them as unsigned ints. I would then create a function for each register which would shift the values into the correct position for their associated register, mask the members together, and then copy them over using the volatile uint32_t pointer to the base address.  


Does this seem like a viable solution? Any thoughts on portability?
0 Kudos