Can not able to read data from custom AXI peripheral register - c

I am working with a Zynq board where a custom AXI 4 lite slave peripheral is created and then added from the IP Repository.
And created a synthesizable custom IP in vivado (which is sine wave IP)and also wrote a C code for reading this IP output ( i want to read a data from the register). But somehow it shows something diff. instead of what I expect.
Here I'm attaching a screenshot and my c code for that.
But in teraterm it shows some garbage memory state.
Here, I'm expecting a sinewave output. ( In digit form )
Pls, suggest me correction or suggestion about Where could I have gone wrong or what have I missed in C code?.
#include "xil_printf.h"
#include "xil_io.h"
#include "xparameters.h"
#include "xil_types.h"
#include "xparameters_ps.h"
#include <stdio.h>
//Definitions for peripheral MYIPINETHREE_0 //
#define XPAR_ MYIPINETHREE_0_DEVICE_ID 0
#define XPAR_ MYIPINETHREE_0_S00_AXI_BASEADDR 0x43C00000
#define XPAR_ MYIPINETHREE_0_S00_AXI_HIGHADDR 0x43C0FFFF
int main(){
u32 baseaddr;
int sine, sinephase, enable,reg ;
while (1)
{
xil_printf("start of ip test\r");
if (enable == 1)
reg = 0xFFFFFFFF;
else
reg = 0x00000000;
Xil_Out32(0x43C00000, 32 );
sine = Xil_In32(baseaddr+4);
xil_printf("\r state: %d", sine);
Xil_Out32(0x43C00000, 32);
sinephase = Xil_In32(baseaddr+4);
xil_printf("\r state: %d", sinephase);
return 0;
}
}

To start with: you never initialize baseaddr but use it to read from.
Also I can't say because I have no idea how to verify that your addresses are correct. Normally you should use the defines from your xparameters.h file where the Xilinx board package program puts them. I don't see that happening here.
I am somewhat suspicious as all my Xilinx AXI addresses start with 0x800... but then I might be because I am using a different FPGA.

Please add a board layout or some additional information. You should use the addresses from xparameters.hinstead of hard coding them into your source code. The address space depends on your AXI master interface.

Related

Running a block of code from RAM instead of flash

In the following program, what is the meaning of the line of code
fnRAM_code((volatile unsigned char *)FLASH_STATUS_REGISTER); // execute the command from SRAM
in the below section of code. I have some idea about what is happening here,In order to overcome read while write violation, copying the code from flash to RAM using the above lines of code. But what is exact meaning of these lines.
static int fnProgram(unsigned long *ptrWord, unsigned long *ptr_ulWord)
{
while ((FTFL_FSTAT & FTFL_STAT_CCIF) == 0) {} // wait for previous commands to complete
if ((FTFL_FSTAT & (FTFL_STAT_ACCERR | FTFL_STAT_FPVIOL | FTFL_STAT_RDCOLERR)) != 0) { // check for errors in previous command
FTFL_FSTAT = (FTFL_STAT_ACCERR | FTFL_STAT_FPVIOL | FTFL_STAT_RDCOLERR); // clear old errors
}
FTFL_FCCOB0 = FCMD_PROGRAM; // enter the command sequence
FTFL_FCCOB1 = (unsigned char)(((CAST_POINTER_ARITHMETIC)ptrWord) >> 16); // set address in flash
FTFL_FCCOB2 = (unsigned char)(((CAST_POINTER_ARITHMETIC)ptrWord) >> 8);
FTFL_FCCOB3 = (unsigned char)((CAST_POINTER_ARITHMETIC)ptrWord);
FTFL_FCCOB7_4 = *ptr_ulWord++; // enter the long word to be programmed
FTFL_FCCOBB_8 = *ptr_ulWord; // enter the second long word to be programmed
uDisable_Interrupt(); // protect this region from interrupts
fnRAM_code((volatile unsigned char *)FLASH_STATUS_REGISTER); // execute the command from SRAM
uEnable_Interrupt(); // safe to accept interrupts again
return (FTFL_FSTAT & (FTFL_STAT_ACCERR | FTFL_STAT_FPVIOL | FTFL_STAT_MGSTAT0)); // if there was an error this will be non-zero
}
The only code that needs to be in RAM is this:
static void fnFlashRoutineInRam(volatile unsigned char *ptrFTFL_BLOCK)
{
*ptrFTFL_BLOCK = FTFL_STAT_CCIF; // launch the command - this clears the FTFL_STAT_CCIF flag (register is FTFL_FSTAT)
while ((*ptrFTFL_BLOCK & FTFL_STAT_CCIF) == 0) {} // wait for the command to terminate
}
This looks like older NXP (former Freescale/Motorola) HCS08, HCS12 or Coldfire. On those devices, you have different cases when writing a flash driver: either you can execute it from flash or you cannot. This entirely depends on which "bank" the program flash belongs to: generally you cannot execute code on a MCU from the very same flash bank it is currently programming.
So ideally you put the flash programming code in another bank, but some devices only have one single flash bank. Then they provide a work-around by executing the code from RAM, which is kind of a quick & dirty fix.
Commonly they solve this by providing an array of raw data op codes. This array of op codes is copied to RAM and then they set a function pointer to point at the RAM address. I suspect fnRAM_code is such a function pointer. The (volatile unsigned char *)FLASH_STATUS_REGISTER part is simply passing on the address of the flash status register. Likely, FLASH_STATUS_REGISTER is synonymous with FSTAT.
The uDisable_Interrupt(); and uEnable_Interrupt(); should correspond to asm SEI and asm CLI respectively, blocking all maskable interrupts from triggering during the flash write, which would potentially cause the write to fail or the program to hang up.
There should be app notes available describing all of this in detail.
Please note that this code is very close to the hardware and relies on tons of poorly-defined behavior. I wouldn't count on it compiling as expected on anything but the Codewarrior compiler. gcc would for example spew out numerous strict aliasing bugs.

Uart receives correct Bytes but in chaotic order

Using Atmel studio 7, with STK600 and 32UC3C MCU
I'm pulling my hair over this.
I'm sending strings of a variable size over UART once every 5 seconds. The String consists of one letter as opcode, then two chars are following that tell the lenght of the following datastring (without the zero, there is never a zero at the end of any of those strings). In most cases the string will be 3 chars in size, because it has no data ("p00").
After investigation I found out that what supposed to be "p00" was in fact "0p0" or "00p" or (only at first try after restarting the micro "p00"). I looked it up in the memory view of the debugger. Then I started hTerm and confirmed that the data was in fact "p00". So after a while hTerm showed me "p00p00p00p00p00p00p00..." while the memory of my circular uart buffer reads "p000p000p0p000p0p000p0p0..."
edit: Actually "0p0" and "00p" are alternating.
The baud rate is 9600. In the past I was only sending single letters. So everything was running well.
This is the code of the Receiver Interrupt:
I tried different variations in code that were all doing the same in a different way. But all of them showed the exact same behavior.
lastWebCMDWritePtr is a uint8_t* type and so is lastWebCMDRingstartPtr.
lastWebCMDRingRXLen is a uint8_t type.
__attribute__((__interrupt__))
void UartISR_forWebserver()
{
*(lastWebCMDWritePtr++) = (uint8_t)((&AVR32_USART0)->rhr & 0x1ff);
lastWebCMDRingRXLen++;
if(lastWebCMDWritePtr - lastWebCMDRingstartPtr > lastWebCMDRingBufferSIZE)
{
lastWebCMDWritePtr = lastWebCMDRingstartPtr;
}
// Variation 2:
// advanceFifo((uint8_t)((&AVR32_USART0)->rhr & 0x1ff));
// Variation 3:
// if(usart_read_char(&AVR32_USART0, getReadPointer()) == USART_RX_ERROR)
// {
// usart_reset_status(&AVR32_USART0);
// }
//
};
I welcome any of your ideas and advices.
Regarts Someo
P.S. I put the Atmel studio tag in case this has something to do with the myriad of debugger bugs of AS.
For a complete picture you would have to show where and how lastWebCMDWritePtr, lastWebCMDRingRXLen, lastWebCMDRingstartPtr and lastWebCMDRingBufferSIZE are used elsewhere (on the consuming side)
Also I would first try a simpler ISR with no dependencies to other software modules to exclude a hardware resp. register handling problem.
Approach:
#define USART_DEBUG
#define DEBUG_BUF_SIZE 30
__attribute__((__interrupt__))
void UartISR_forWebserver()
{
uint8_t rec_byte;
#ifdef USART_DEBUG
static volatile uint8_t usart_debug_buf[DEBUG_BUF_SIZE]; //circular buffer for debugging
static volatile int usart_debug_buf_index = 0;
#endif
rec_byte = (uint8_t)((&AVR32_USART0)->rhr & 0x1ff);
#ifdef USART_DEBUG
usart_debug_buf_index = usart_debug_buf_index % DEBUG_BUF_SIZE;
usart_debug_buf[usart_debug_buf_index] = rec_byte;
usart_debug_buf_index++
if (!(usart_debug_buf_index < DEBUG_BUF_SIZE)) {
usart_debug_buf_index = 0; //candidate for a breakpoint to see what happened in the past
}
#endif
//uart_recfifo_enqueue(rec_byte);
};

mbed-OS porting to TivaC TM4123, Trouple with dynamic interrupt handling

Recently I'm trying to port mbed-OS to Tiva-C launchpad TM4C123, I am facing problem with file supplied by mbed which is cmsis_nvic.c and cmsis_nvic.h
This module is supposed to dynamically allocate the interrupt handler of OS timer to addressable function.(Or as far as I understand).
What happen is, The software jumps to "Hard Fault Handler" after executing the following line
vectors[i] = old_vectors[i];
Here's files which I use
#include "cmsis_nvic.h"
#define NVIC_RAM_VECTOR_ADDRESS (0x02000000) // Vectors positioned at start of RAM
#define NVIC_FLASH_VECTOR_ADDRESS (0x0) // Initial vector position in flash
void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) {
uint32_t *vectors = (uint32_t*)SCB->VTOR;
uint32_t i;
// Copy and switch to dynamic vectors if the first time called
if (SCB->VTOR == NVIC_FLASH_VECTOR_ADDRESS) {
uint32_t *old_vectors = vectors;
vectors = (uint32_t*)NVIC_RAM_VECTOR_ADDRESS;
for (i=0; i<NVIC_NUM_VECTORS; i++) {
vectors[i] = old_vectors[i];
}
SCB->VTOR = (uint32_t)NVIC_RAM_VECTOR_ADDRESS;
}
vectors[IRQn + 16] = vector;
}
uint32_t NVIC_GetVector(IRQn_Type IRQn) {
uint32_t *vectors = (uint32_t*)SCB->VTOR;
return vectors[IRQn + 16];
}
And here is cmsis_nvic.h
#ifndef MBED_CMSIS_NVIC_H
#define MBED_CMSIS_NVIC_H
#define NVIC_NUM_VECTORS (154) // CORE + MCU Peripherals
#define NVIC_USER_IRQ_OFFSET 16
#include "cmsis.h"
#ifdef __cplusplus
extern "C" {
#endif
void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector);
uint32_t NVIC_GetVector(IRQn_Type IRQn);
#ifdef __cplusplus
}
#endif
#endif
and I am calling
NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
from file us_ticker.c like this
NVIC_SetVector(TIMER0A_IRQn, (uint32_t)us_ticker_irq_handler);
(my compiler is ARM GCC, I am using CDT for building, And GDB openOCD for debugging, and integrated all those tools on Eclipse)
Can anyone please let me know what is going wrong here? or at least where should I debug or read to help me solve this problem???
UPDATE
I figured out part of the problem, The vector is not pointing to the first address of the target SRAM which should be
#define NVIC_RAM_VECTOR_ADDRESS (0x20000000)
instead of
#define NVIC_RAM_VECTOR_ADDRESS (0x02000000)
So now when calling NVIC_SetVector , the function is executed. But then when enabling the interrupt, Software still jumps to Hard Fault, I guess(just guessing or might be part of solution) that the defines in the header file are not configured correctly, Can someone explain to me what do they mean? and how to calculate the number of vector addresses? and what is the USER OFFSET?
I have solved this issue, here's what I have found
1- NVIC_RAM_VECTOR_ADDRESS wasn't the first address of my target RAM which should be `0x20000000'
2- Linker file should be update so that the stack pointer shouldn't write over the new copied vector table. So shift the RAM address by number of bytes that vector table should occupy.
3-(THE MAIN CAUSE) inside function NVIC_SetVector, i was declared as uint32_t and then compared to less than 255 pre-processor value. So compile get confused by comparing uint32_t with uint8_t, by adding UL to the pre-processor value, it solved the whole issue.

C code repetition with small variances by means of preprocessor macros

I'm currently working on some peripheral drivers for a family of microprocessors. I need to write code for devices that are very similar that in some cases only vary in the number of peripherals.
I would like to write a driver for the UART peripheral but in some devices of the family there's only one available and for others there are two. The driver for UART2 y the same as for UART1 but instead of writing to UART1FOO register I need to write to UART2FOO register. Knowing this I would like to write a piece of code where a macro is able to repeat a big chunk of code but replacing the number of the register reference.
The ideal solution would be something like:
// File: uartdriver.h
#if __device1__
#define PRESENT_UARTS 1
#else
#define PRESENT_UARTS 2
#endif
#for CURRENT_ITEM in MAGIC_MACRO_THAT_RETURNS_LIST(PRESENT_UARTS)
void uart#CURRENT_ITEM#_init();
#endfor
I know that this pseudo code does not exist but I have also seen people do magic with macros. I must use C code and not C++ and I'm aware that the use of macros may not be the most friendly way to write this but I don't like to repeat code with such small variations.
What would be the best solutions that mimic the pseudocode above? Any other hint or advice? Is there any other alternative to macros in this situation?
Thank you very much for your time.
I think some people are suggesting something along the lines of this. Note, this is pseudo code ie I just typed this in without testing it so it likely has some bugs etc.
typedef uint8_t uart_id;
int uart_init(uart_id id, uint16_t baudrate);
typedef struct uart_definitions {
uart_id id;
uint16_t baudrate;
....
} udefs;
#define MAX_UDEFS 2
static udefs u_config[MAX_UDEFS] = {
{0, 1000},
{1, 8192}
};
uart_init(uart_id id, uint16_t brate) {
assert(id <= MAX_UDEFS);
u_config[id].baudrate = brate;
.....
}

Creating File in arduino's Memory while arduino is operating

In my arduino project i have to store some integers(25 to be specific) in a file in arduino's memory (as i have arduino UNO and it doesn't have built-in port for SD Card) and read that file next-time i start the arduino .
Also my arduino is not connected to PC or laptop so i can't use file system of PC or laptop
so is there any way possible doing it ?
Arduino Uno has 1KB of non-volatile EEPROM memory, which you can use for this purpose. An integer is 2 bytes, so you should be able to store over 500 ints this way.
This example sketch should write a couple of integers from 10 to 5 into EEPROM memory:
#include <EEPROM.h>
void setup() {
int address = 0; //Location we want the data to be put.
for (int value = 10; value >= 5; --value)
{
// Write the int at address
EEPROM.put(eeAddress, value)
// Move the address, so the next value will be written after the first.
address += sizeof(int);
}
}
void loop() {
}
This example is a stripped down version of the one in the EEPROM.put documentation. Other examples can be found in the documentation of the various EEPROM functions.
Another nice tutorial on the subject can be found on tronixstuff.
By the way, if you need more memory, you could also use EEPROM memory banks. These are small ICs. They are available for very low prices in low amounts of memory, typically from 1KB to 256KB. Not much in terms of modern computing, but a huge expansion compared to the 1KB you have by default.

Resources