I have been trying to setup a uart on the EFM32 Starter kind and I am now able to send characters out of the EFM32 Starter kit board to a computer, but when I try to receive from the computer using the example, my interrupt gets called once, but the data I get is 0x0 and then after the first character I dont receive the interrupt again.
I modified the code from the application note software that can be found on silab's website: USART/UART Asynchronous mode Application Note software
I have added the code to this question as well. Has anyone else encountered this? I must be doing something silly.
I checked the RXDATA register in the debugger and it keeps showing 0 even when I press a the "a" character on the keyboard. Also the interrupt only fires once, with the rxdata being 0, then I never get an interrupt after that.
Thanks in advance.
/******************************************************************************
* #file main.c
* #brief USART/UART Asynchronous mode Application Note software example
* #author Silicon Labs
* #version 1.03
******************************************************************************
* #section License
* <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
*******************************************************************************
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
* obligation to support this Software. Silicon Labs is providing the
* Software "AS IS", with no express or implied warranties of any kind,
* including, but not limited to, any implied warranties of merchantability
* or fitness for any particular purpose or warranties against infringement
* of any proprietary rights of a third party.
*
* Silicon Labs will not be liable for any consequential, incidental, or
* special damages, or any other relief, or for any claim by any third party,
* arising from your use of this Software.
*
******************************************************************************/
#include <stdint.h>
#include "em_device.h"
#include "em_chip.h"
#include "em_emu.h"
#include "em_cmu.h"
#include "em_gpio.h"
#include "em_usart.h"
#include "bsp.h"
/* Function prototypes */
void uartSetup(void);
void cmuSetup(void);
void uartPutData(uint8_t * dataPtr, uint32_t dataLen);
uint32_t uartGetData(uint8_t * dataPtr, uint32_t dataLen);
void uartPutChar(uint8_t charPtr);
uint8_t uartGetChar(void);
/* Declare some strings */
const char welcomeString[] = "EFM32 RS-232 - Please press a key\r\n";
const char overflowString[] = "\n---RX OVERFLOW---\n";
const uint32_t welLen = sizeof(welcomeString) - 1;
const uint32_t ofsLen = sizeof(overflowString) - 1;
/* Define termination character */
#define TERMINATION_CHAR '.'
/* Declare a circular buffer structure to use for Rx and Tx queues */
#define BUFFERSIZE 256
volatile struct circularBuffer
{
uint8_t data[BUFFERSIZE]; /* data buffer */
uint32_t rdI; /* read index */
uint32_t wrI; /* write index */
uint32_t pendingBytes; /* count of how many bytes are not yet handled */
bool overflow; /* buffer overflow indicator */
} rxBuf, txBuf = { {0}, 0, 0, 0, false };
/* Setup UART1 in async mode for RS232*/
static USART_TypeDef * uart = USART1;
static USART_InitAsync_TypeDef uartInit = USART_INITASYNC_DEFAULT;
/******************************************************************************
* #brief Main function
*
*****************************************************************************/
int main(void)
{
/* Initialize chip - handle erratas */
CHIP_Init( );
/* Initialize clocks and oscillators */
cmuSetup( );
/* Initialize UART peripheral */
uartSetup( );
/* Initialize Development Kit in EBI mode */
// BSP_Init(BSP_INIT_DEFAULT);
/* Enable RS-232 transceiver on Development Kit */
//BSP_PeripheralAccess(BSP_RS232_UART, true);
/* When DVK is configured, and no more DVK access is needed, the interface can safely be disabled to save current */
//BSP_Disable();
/* Write welcome message to UART */
uartPutData((uint8_t*) welcomeString, welLen);
/* Eternal while loop
* CPU will sleep during Rx and Tx. When a byte is transmitted, an interrupt
* wakes the CPU which copies the next byte in the txBuf queue to the
* UART TXDATA register.
*
* When the predefined termiation character is received, the all pending
* data in rxBuf is copied to txBuf and echoed back on the UART */
while (1)
{
/* Wait in EM1 while UART transmits */
EMU_EnterEM1();
/* Check if RX buffer has overflowed */
if (rxBuf.overflow)
{
rxBuf.overflow = false;
uartPutData((uint8_t*) overflowString, ofsLen);
}
/* Check if termination character is received */
if (rxBuf.data[(rxBuf.wrI - 1) % BUFFERSIZE] == TERMINATION_CHAR)
{
/* Copy received data to UART transmit queue */
uint8_t tmpBuf[BUFFERSIZE];
int len = uartGetData(tmpBuf, 0);
uartPutData(tmpBuf, len);
}
}
}
/******************************************************************************
* #brief uartSetup function
*
******************************************************************************/
void uartSetup(void)
{
/* Enable clock for GPIO module (required for pin configuration) */
CMU_ClockEnable(cmuClock_GPIO, true);
/* Configure GPIO pins */
GPIO_PinModeSet(gpioPortC, 0, gpioModePushPull, 1);
GPIO_PinModeSet(gpioPortC, 1, gpioModeInput, 0);
/* Prepare struct for initializing UART in asynchronous mode*/
uartInit.enable = usartDisable; /* Don't enable UART upon intialization */
uartInit.refFreq = 0; /* Provide information on reference frequency. When set to 0, the reference frequency is */
uartInit.baudrate = 115200; /* Baud rate */
uartInit.oversampling = usartOVS16; /* Oversampling. Range is 4x, 6x, 8x or 16x */
uartInit.databits = usartDatabits8; /* Number of data bits. Range is 4 to 10 */
uartInit.parity = usartNoParity; /* Parity mode */
uartInit.stopbits = usartStopbits1; /* Number of stop bits. Range is 0 to 2 */
// uartInit.mvdis = false; /* Disable majority voting */
// uartInit.prsRxEnable = false; /* Enable USART Rx via Peripheral Reflex System */
// uartInit.prsRxCh = usartPrsRxCh0; /* Select PRS channel if enabled */
/* Initialize USART with uartInit struct */
USART_InitAsync(uart, &uartInit);
/* Prepare UART Rx and Tx interrupts */
USART_IntClear(uart, _UART_IFC_MASK);
USART_IntEnable(uart, UART_IEN_RXDATAV);
NVIC_ClearPendingIRQ(USART1_RX_IRQn);
NVIC_ClearPendingIRQ(USART1_TX_IRQn);
NVIC_EnableIRQ(USART1_RX_IRQn);
NVIC_EnableIRQ(USART1_TX_IRQn);
/* Enable I/O pins at UART1 location #2 */
uart->ROUTE = UART_ROUTE_RXPEN | UART_ROUTE_TXPEN | UART_ROUTE_LOCATION_LOC0;
/* Enable UART */
USART_Enable(uart, usartEnable);
}
/******************************************************************************
* #brief uartGetChar function
*
* Note that if there are no pending characters in the receive buffer, this
* function will hang until a character is received.
*
*****************************************************************************/
uint8_t uartGetChar( )
{
uint8_t ch;
/* Check if there is a byte that is ready to be fetched. If no byte is ready, wait for incoming data */
if (rxBuf.pendingBytes < 1)
{
while (rxBuf.pendingBytes < 1) ;
}
/* Copy data from buffer */
ch = rxBuf.data[rxBuf.rdI];
rxBuf.rdI = (rxBuf.rdI + 1) % BUFFERSIZE;
/* Decrement pending byte counter */
rxBuf.pendingBytes--;
return ch;
}
/******************************************************************************
* #brief uartPutChar function
*
*****************************************************************************/
void uartPutChar(uint8_t ch)
{
/* Check if Tx queue has room for new data */
if ((txBuf.pendingBytes + 1) > BUFFERSIZE)
{
/* Wait until there is room in queue */
while ((txBuf.pendingBytes + 1) > BUFFERSIZE) ;
}
/* Copy ch into txBuffer */
txBuf.data[txBuf.wrI] = ch;
txBuf.wrI = (txBuf.wrI + 1) % BUFFERSIZE;
/* Increment pending byte counter */
txBuf.pendingBytes++;
/* Enable interrupt on USART TX Buffer*/
USART_IntEnable(uart, UART_IEN_TXBL);
}
/******************************************************************************
* #brief uartPutData function
*
*****************************************************************************/
void uartPutData(uint8_t * dataPtr, uint32_t dataLen)
{
uint32_t i = 0;
/* Check if buffer is large enough for data */
if (dataLen > BUFFERSIZE)
{
/* Buffer can never fit the requested amount of data */
return;
}
/* Check if buffer has room for new data */
if ((txBuf.pendingBytes + dataLen) > BUFFERSIZE)
{
/* Wait until room */
while ((txBuf.pendingBytes + dataLen) > BUFFERSIZE) ;
}
/* Fill dataPtr[0:dataLen-1] into txBuffer */
while (i < dataLen)
{
txBuf.data[txBuf.wrI] = *(dataPtr + i);
txBuf.wrI = (txBuf.wrI + 1) % BUFFERSIZE;
i++;
}
/* Increment pending byte counter */
txBuf.pendingBytes += dataLen;
/* Enable interrupt on USART TX Buffer*/
USART_IntEnable(uart, UART_IEN_TXBL);
}
/******************************************************************************
* #brief uartGetData function
*
*****************************************************************************/
uint32_t uartGetData(uint8_t * dataPtr, uint32_t dataLen)
{
uint32_t i = 0;
/* Wait until the requested number of bytes are available */
if (rxBuf.pendingBytes < dataLen)
{
while (rxBuf.pendingBytes < dataLen) ;
}
if (dataLen == 0)
{
dataLen = rxBuf.pendingBytes;
}
/* Copy data from Rx buffer to dataPtr */
while (i < dataLen)
{
*(dataPtr + i) = rxBuf.data[rxBuf.rdI];
rxBuf.rdI = (rxBuf.rdI + 1) % BUFFERSIZE;
i++;
}
/* Decrement pending byte counter */
rxBuf.pendingBytes -= dataLen;
return i;
}
/***************************************************************************//**
* #brief Set up Clock Management Unit
******************************************************************************/
void cmuSetup(void)
{
/* Start HFXO and wait until it is stable */
/* CMU_OscillatorEnable( cmuOsc_HFXO, true, true); */
/* Select HFXO as clock source for HFCLK */
/* CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO ); */
/* Disable HFRCO */
/* CMU_OscillatorEnable( cmuOsc_HFRCO, false, false ); */
/* Enable clock for HF peripherals */
CMU_ClockEnable(cmuClock_HFPER, true);
/* Enable clock for USART module */
CMU_ClockEnable(cmuClock_USART1, true);
}
/**************************************************************************//**
* #brief UART1 RX IRQ Handler
*
* Set up the interrupt prior to use
*
* Note that this function handles overflows in a very simple way.
*
*****************************************************************************/
void USART1_RX_IRQHandler(void)
{
/* Check for RX data valid interrupt */
if (uart->IF & UART_IF_RXDATAV)
{
/* Copy data into RX Buffer */
uint8_t rxData = USART_Rx(uart);
rxBuf.data[rxBuf.wrI] = rxData;
rxBuf.wrI = (rxBuf.wrI + 1) % BUFFERSIZE;
rxBuf.pendingBytes++;
/* Flag Rx overflow */
if (rxBuf.pendingBytes > BUFFERSIZE)
{
rxBuf.overflow = true;
}
}
}
/**************************************************************************//**
* #brief UART1 TX IRQ Handler
*
* Set up the interrupt prior to use
*
*****************************************************************************/
void USART1_TX_IRQHandler(void)
{
/* Check TX buffer level status */
if (uart->IF & UART_IF_TXBL)
{
if (txBuf.pendingBytes > 0)
{
/* Transmit pending character */
USART_Tx(uart, txBuf.data[txBuf.rdI]);
txBuf.rdI = (txBuf.rdI + 1) % BUFFERSIZE;
txBuf.pendingBytes--;
}
/* Disable Tx interrupt if no more bytes in queue */
if (txBuf.pendingBytes == 0)
{
USART_IntDisable(uart, UART_IEN_TXBL);
}
}
}
I am using FT2232H-56Q. I want to use the SPI channels. I downloaded the libMPSSE-SPI example.
I am using the sample example "sample-static.c". When I run the exe I always get this message:
Press any key to continue . . . Number of available SPI channels = 0
This happens even when the device is connected.
Code:
/*!
* \file sample-static.c
*
* \author FTDI
* \date 20110512
*
* Copyright © 2000-2014 Future Technology Devices International Limited
*
*
* THIS SOFTWARE IS PROVIDED BY FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* Project: libMPSSE
* Module: SPI Sample Application - Interfacing 94LC56B SPI EEPROM
*
* Rivision History:
* 0.1 - 20110512 - Initial version
* 0.2 - 20110801 - Changed LatencyTimer to 255
* Attempt to open channel only if available
* Added & modified macros
* Included stdlib.h
* 0.3 - 20111212 - Added comments
* 0.41 - 20140903 - Fixed compilation warnings
* Added testing of SPI_ReadWrite()
*/
/******************************************************************************/
/* Include files */
/******************************************************************************/
/* Standard C libraries */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <assert.h>
//#include <vector.h>
#include <stdbool.h>
//#include <random>
/* OS specific libraries */
#ifdef _WIN32
#include<windows.h>
#endif
/* Include D2XX header*/
#include "ftd2xx.h"
/* Include libMPSSE header */
#include "libMPSSE_spi.h"
/******************************************************************************/
/* Macro and type defines */
/******************************************************************************/
/* Helper macros */
#define APP_CHECK_STATUS(exp) {if(exp!=FT_OK){printf("%s:%d:%s(): status(0x%x) \
!= FT_OK\n",__FILE__, __LINE__, __FUNCTION__,exp);exit(1);}else{;}};
#define CHECK_NULL(exp){if(exp==NULL){printf("%s:%d:%s(): NULL expression \
encountered \n",__FILE__, __LINE__, __FUNCTION__);exit(1);}else{;}};
/* Application specific macro definations */
#define SPI_DEVICE_BUFFER_SIZE 256
#define SPI_WRITE_COMPLETION_RETRY 10
#define START_ADDRESS_EEPROM 0x00 /*read/write start address inside the EEPROM*/
#define END_ADDRESS_EEPROM 0x10
#define RETRY_COUNT_EEPROM 10 /* number of retries if read/write fails */
#define CHANNEL_TO_OPEN 0 /*0 for first available channel, 1 for next... */
#define SPI_SLAVE_0 0
#define SPI_SLAVE_1 1
#define SPI_SLAVE_2 2
#define DATA_OFFSET 4
#define USE_WRITEREAD 0
/******************************************************************************/
/* Global variables */
/******************************************************************************/
static FT_HANDLE ftHandle;
static uint8 buffer[SPI_DEVICE_BUFFER_SIZE] = {0};
static FT_DEVICE_LIST_INFO_NODE *devList;
static uint32 numberChannels;
/******************************************************************************/
/* Public function definitions */
/******************************************************************************/
/**
* #brief Initializes the comBridge
* Must be called first
* #param[out] noChannels: Number of available channels
* #param[out] channelId[]: Description of the devices with their index being identical to the channel selector in all other functions
* #return Device status with FT_OK = 0
*/
FT_STATUS comBridge_initialize(uint32 *noChannels, char *channelId[]) {
Init_libMPSSE();
FT_STATUS status = FT_OK;
// get number of channels
status = SPI_GetNumChannels(noChannels);
numberChannels = *noChannels;
APP_CHECK_STATUS(status);
#ifdef VERBOSE
printf("ComBridge initialized\n");
printf(" SPI channels %d\n\n", *noChannels);
#endif // VERBOSE
// get channel infos
devList = (FT_DEVICE_LIST_INFO_NODE *)calloc(*noChannels, sizeof(FT_DEVICE_LIST_INFO_NODE));
for (uint32 channelIndex = 0; channelIndex < *noChannels; channelIndex++) {
status = SPI_GetChannelInfo(channelIndex, devList);
APP_CHECK_STATUS(status);
strcpy(channelId[channelIndex], devList->Description);
#ifdef VERBOSE
printf("Channel %d info\n", channelIndex);
printf(" Flags 0x%x\n", devList->Flags);
printf(" Type 0x%x\n", devList->Type);
printf(" ID 0x%x\n", devList->ID);
printf(" LocId 0x%x\n", devList->LocId);
printf(" SerialNumber %s\n", devList->SerialNumber);
printf(" Description %s\n", devList->Description);
//printf(" ftHandle=0x%x\n", (unsigned int)devList->ftHandle);
printf("\n");
#endif // VERBOSE
};
return status;
}
/**
* #brief Opens and initilizes a SPI channel
* Must be called after comBridge_initialize() and for each channel individually
* Latency = 255 ms, that "xDBUS3 of MPSSE is chip select" and that "chip select is active high" are predefined and cannot be changed manually
* #param[in] channel: Selects a channel via the index of the corresponding element in the channelId[] array
* #param[in] clockRate_Hz: Clock rate of the SPI bus in Hz (0..10 MHz)
* #param[in] spiMode: Selects SPI Mode (SPI_CONFIG_OPTION_MODE0 or SPI_CONFIG_OPTION_MODE3)
* #return Device status with FT_OK = 0
*/
FT_STATUS comBridge_setup(uint32 channel, uint32 clockRate_Hz, uint32 spiMode) {
FT_STATUS status = FT_OK;
assert(channel < numberChannels);
assert(clockRate_Hz <= 10000000);
assert((spiMode == SPI_CONFIG_OPTION_MODE0) | (spiMode == SPI_CONFIG_OPTION_MODE3));
status = SPI_OpenChannel(channel, &devList[channel].ftHandle);
APP_CHECK_STATUS(status);
ChannelConfig channelConf = {
5000, // ClockRate
255, // LatencyTime
SPI_CONFIG_OPTION_MODE0 | SPI_CONFIG_OPTION_CS_DBUS3 | SPI_CONFIG_OPTION_CS_ACTIVELOW, // configOptions
0x00000000 // Pin
};
channelConf.ClockRate = clockRate_Hz;
channelConf.configOptions = spiMode | SPI_CONFIG_OPTION_CS_DBUS3 | SPI_CONFIG_OPTION_CS_ACTIVELOW;
status = SPI_InitChannel(devList[channel].ftHandle, &channelConf);
APP_CHECK_STATUS(status);
#ifdef VERBOSE
printf("Channel %d opened\n", channel);
printf(" ClockRate %d\n", channelConf.ClockRate);
printf(" Latency %d\n", channelConf.LatencyTimer);
printf(" Config %d\n", channelConf.configOptions);
printf(" Pin %d\n\n", channelConf.Pin);
//printf(" Handle=%ld\n", (uint32)devList[channel].ftHandle);
#endif // VERBOSE
// sets all GPIO pins as input
status = FT_WriteGPIO(devList[channel].ftHandle, 0b00000000, 0b00000000);
APP_CHECK_STATUS(status);
return status;
}
/*!
* \brief Writes to EEPROM
*
* This function writes a byte to a specified address within the 93LC56B EEPROM
*
* \param[in] slaveAddress Address of the I2C slave (EEPROM)
* \param[in] registerAddress Address of the memory location inside the slave to where the byte
* is to be written
* \param[in] data The byte that is to be written
* \return Returns status code of type FT_STATUS(see D2XX Programmer's Guide)
* \sa Datasheet of 93LC56B http://ww1.microchip.com/downloads/en/DeviceDoc/21794F.pdf
* \note
* \warning
*/
static FT_STATUS read_byte(uint8 slaveAddress, uint8 address, uint16 *data)
{
uint32 sizeToTransfer = 0;
uint32 sizeTransfered;
uint8 writeComplete=0;
uint32 retry=0;
FT_STATUS status;
/* CS_High + Write command + Address */
sizeToTransfer=1;
sizeTransfered=0;
buffer[0] = 0xC0;/* Write command (3bits)*/
buffer[0] = buffer[0] | ( ( address >> 3) & 0x0F );/*5 most significant add bits*/
status = SPI_Write(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES|
SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE);
APP_CHECK_STATUS(status);
/*Write partial address bits */
sizeToTransfer=4;
sizeTransfered=0;
buffer[0] = ( address & 0x07 ) << 5; /* least significant 3 address bits */
status = SPI_Write(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BITS);
APP_CHECK_STATUS(status);
/*Read 2 bytes*/
sizeToTransfer=2;
sizeTransfered=0;
status = SPI_Read(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES|
SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE);
APP_CHECK_STATUS(status);
*data = (uint16)(buffer[1]<<8);
*data = (*data & 0xFF00) | (0x00FF & (uint16)buffer[0]);
return status;
}
/*!
* \brief Reads from EEPROM
*
* This function reads a byte from a specified address within the 93LC56B EEPROM
*
* \param[in] slaveAddress Address of the I2C slave (EEPROM)
* \param[in] registerAddress Address of the memory location inside the slave from where the
* byte is to be read
* \param[in] *data Address to where the byte is to be read
* \return Returns status code of type FT_STATUS(see D2XX Programmer's Guide)
* \sa Datasheet of 93LC56B http://ww1.microchip.com/downloads/en/DeviceDoc/21794F.pdf
* \note
* \warning
*/
static FT_STATUS write_byte(uint8 slaveAddress, uint8 address, uint16 data)
{
uint32 sizeToTransfer = 0;
uint32 sizeTransfered=0;
uint8 writeComplete=0;
uint32 retry=0;
FT_STATUS status;
/* Write command EWEN(with CS_High -> CS_Low) */
sizeToTransfer=11;
sizeTransfered=0;
buffer[0]=0x9F;/* SPI_EWEN -> binary 10011xxxxxx (11bits) */
buffer[1]=0xFF;
status = SPI_Write(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BITS|
SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE|
SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE);
APP_CHECK_STATUS(status);
/* CS_High + Write command + Address */
sizeToTransfer=1;
sizeTransfered=0;
buffer[0] = 0xA0;/* Write command (3bits) */
buffer[0] = buffer[0] | ( ( address >> 3) & 0x0F );/*5 most significant add bits*/
status = SPI_Write(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES|
SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE);
APP_CHECK_STATUS(status);
/*Write 3 least sig address bits */
sizeToTransfer=3;
sizeTransfered=0;
buffer[0] = ( address & 0x07 ) << 5; /* least significant 3 address bits */
status = SPI_Write(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BITS);
APP_CHECK_STATUS(status);
/* Write 2 byte data + CS_Low */
sizeToTransfer=2;
sizeTransfered=0;
buffer[0] = (uint8)(data & 0xFF);
buffer[1] = (uint8)((data & 0xFF00)>>8);
status = SPI_Write(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES|
SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE);
APP_CHECK_STATUS(status);
/* Wait until D0 is high */
#if 1
/* Strobe Chip Select */
sizeToTransfer=0;
sizeTransfered=0;
status = SPI_Write(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BITS|
SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE);
APP_CHECK_STATUS(status);
#ifndef __linux__
Sleep(10);
#endif
sizeToTransfer=0;
sizeTransfered=0;
status = SPI_Write(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BITS|
SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE);
APP_CHECK_STATUS(status);
#else
retry=0;
state=FALSE;
SPI_IsBusy(ftHandle,&state);
while((FALSE==state) && (retry<SPI_WRITE_COMPLETION_RETRY))
{
printf("SPI device is busy(%u)\n",(unsigned)retry);
SPI_IsBusy(ftHandle,&state);
retry++;
}
#endif
/* Write command EWEN(with CS_High -> CS_Low) */
sizeToTransfer=11;
sizeTransfered=0;
buffer[0]=0x8F;/* SPI_EWEN -> binary 10011xxxxxx (11bits) */
buffer[1]=0xFF;
status = SPI_Write(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BITS|
SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE|
SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE);
APP_CHECK_STATUS(status);
return status;
}
/*!
* \brief Main function / Entry point to the sample application
*
* This function is the entry point to the sample application. It opens the channel, writes to the
* EEPROM and reads back.
*
* \param[in] none
* \return Returns 0 for success
* \sa
* \note
* \warning
*/
int main()
{
uint32 noChannels = 0;
char *channelId[10];
char channelIdArray[10][46] = { { '\0' } };
for (int i = 0; i < sizeof(channelId); i++)
channelId[i] = channelIdArray[i];
comBridge_initialize(&noChannels, channelId);
for (uint32 channel = 0; channel < noChannels; channel++)
{
//cout << "Channel " << channel << ": " << channelId[channel] << endl;
comBridge_setup(channel, 100000, SPI_CONFIG_OPTION_MODE0);
comBridge_release(channel);
}
FT_STATUS status = FT_OK;
FT_DEVICE_LIST_INFO_NODE devList = {0};
ChannelConfig channelConf = {0};
uint8 address = 0;
uint32 channels = 0;
uint16 data = 0;
uint8 i = 0;
uint8 latency = 255;
channelConf.ClockRate = 5000;
channelConf.LatencyTimer = latency;
channelConf.configOptions = SPI_CONFIG_OPTION_MODE0 | SPI_CONFIG_OPTION_CS_DBUS3;// | SPI_CONFIG_OPTION_CS_ACTIVELOW;
channelConf.Pin = 0x00000000;/*FinalVal-FinalDir-InitVal-InitDir (for dir 0=in, 1=out)*/
/* init library */
#ifdef _MSC_VER
Init_libMPSSE();
#endif
status = SPI_GetNumChannels(&channels);
APP_CHECK_STATUS(status);
printf("Number of available SPI channels = %d\n",(int)channels);
if(channels>0)
{
for(i=0;i<channels;i++)
{
status = SPI_GetChannelInfo(i,&devList);
APP_CHECK_STATUS(status);
printf("Information on channel number %d:\n",i);
/* print the dev info */
printf(" Flags=0x%x\n",devList.Flags);
printf(" Type=0x%x\n",devList.Type);
printf(" ID=0x%x\n",devList.ID);
printf(" LocId=0x%x\n",devList.LocId);
printf(" SerialNumber=%s\n",devList.SerialNumber);
printf(" Description=%s\n",devList.Description);
printf(" ftHandle=0x%x\n",(unsigned int)devList.ftHandle);/*is 0 unless open*/
}
/* Open the first available channel */
status = SPI_OpenChannel(CHANNEL_TO_OPEN,&ftHandle);
APP_CHECK_STATUS(status);
printf("\nhandle=0x%x status=0x%x\n",(unsigned int)ftHandle,status);
status = SPI_InitChannel(ftHandle,&channelConf);
APP_CHECK_STATUS(status);
#if USE_WRITEREAD
{
uint8 k,l;
uint8 inBuffer[100];
uint8 outBuffer[]={0x81,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39};
uint32 sizeToTransfer,sizeTransferred;
for(k=0; k<5; k++)
{
printf("LoopCount = %u ",(unsigned)k);
sizeToTransfer=10;
sizeTransferred=0;
#if 1 // BYTES
status = SPI_ReadWrite(ftHandle, inBuffer, outBuffer+k, sizeToTransfer, &sizeTransferred,
SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES|
SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE|
SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE);
#else // BITES
status = SPI_ReadWrite(ftHandle, inBuffer, outBuffer+k, sizeToTransfer*8, &sizeTransferred,
SPI_TRANSFER_OPTIONS_SIZE_IN_BITS|
SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE|
SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE);
#endif
APP_CHECK_STATUS(status);
printf("status=0x%x sizeTransferred=%u\n", status, sizeTransferred);
for(l=0;l<sizeToTransfer;l++)
printf("0x%x\n",(unsigned)inBuffer[l]);
printf("\n");
}
}
#else // USE_WRITEREAD
for(address=START_ADDRESS_EEPROM;address<END_ADDRESS_EEPROM;address++)
{
printf("writing address = %02d data = %d\n",address,address+DATA_OFFSET);
write_byte(SPI_SLAVE_0, address,(uint16)address+DATA_OFFSET);
}
for(address=START_ADDRESS_EEPROM;address<END_ADDRESS_EEPROM;address++)
{
read_byte(SPI_SLAVE_0, address,&data);
printf("reading address = %02d data = %d\n",address,data);
}
#endif // USE_WRITEREAD
status = SPI_CloseChannel(ftHandle);
}
#ifdef _MSC_VER
Cleanup_libMPSSE();
#endif
#ifndef __linux__
system("pause");
#endif
return 0;
}
I also have the same problem with FT2232H / win7Pro.
The root cause is libMPSSE get wrong locID and judge that the device is not available since D2XX always returns LocId=0 to libMPSSE.
ftdi_mid.c
case FT_DEVICE_2232H:
if(((devList.LocId & 0xf)==1)|| ((devList.LocId & 0xf)==2))
{
isMPSSEAvailable = MID_MPSSE_AVAILABLE;
}
break;
I modify the condition and re-compile libMPSSE with mingw64. It just works.
I had a similar problem on Ubuntu 19.10. The root cause of this was the kernel module that was interacting with FTDI once it was connected and preventing me to connect with it.
The solution was to unload that kernel module:
sudo rmmod ftdi_sio
It is also mentioned in the libftd2xx ReadMe file:
If the message "FT_Open failed" appears:
Perhaps the kernel automatically loaded another driver for the
FTDI USB device.
sudo lsmod
If "ftdi_sio" is listed:
Unload it (and its helper module, usbserial), as follows.
sudo rmmod ftdi_sio
sudo rmmod usbserial
Otherwise, it's possible that libftd2xx does not recognise your
device's Vendor and Product Identifiers. Call FT_SetVIDPID before
calling FT_Open/FT_OpenEx/FT_ListDevices.
I've wrote a letter to FTDI Chip with the question. The support send an updated library that works. The version of library is 0.6 (beta).
I am working on Zynq 702 Evaluation Board where I am trying to send and receive data using UART interface. My code works fine when I generate the bitstream from Vivado after selecting the Zynq 702 board in project settings but the same code doesn't work when I specify the corresponding part number(xc7z020clg484-1) in Vivado and then generate the bitstream. (Need to use part number as I will be using custom boards in the future)
Following is the code snippet for sending data:
for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {
/* Wait until there is space in TX FIFO */
while (XUartPs_IsTransmitFull(UartBaseAddress));
/* Write the byte into the TX FIFO */
XUartPs_WriteReg(UartBaseAddress, XUARTPS_FIFO_OFFSET,
SendBuffer[Index]);
}
The above code works perfectly fine for both with Zynq Board and when using part number.
However I am unable to receive data from UART using following code. This works perfectly when specifying Zynq Board instead of part number in Vivado:
Running = TRUE;
while (Running) {
/* Wait until there is data */
while (!XUartPs_IsReceiveData(UartBaseAddress));
while(recvCount<4)
{
input.bytes_array[recvCount]=XUartPs_RecvByte(UartBaseAddress);
recvCount++;
}
}
The above code is unable to hit the while(recvCount<4) code (on debugging) after sending data through UART terminal(when using part number in Vivado). What could be the problem here? Everything in Vivado block design is the same except the specification of board in one case and part number in the other.
Edit: adding main function and corresponding code:
#include "xparameters.h"
#include "xstatus.h"
#include "xil_types.h"
#include "xil_assert.h"
#include "xuartps_hw.h"
#include "xil_printf.h"
#include "xtime_l.h"
#include <stdio.h>
#include <math.h>
#include "xuartps.h"
#define UART_BASEADDR XPAR_XUARTPS_0_BASEADDR
#define UART_CLOCK_HZ XPAR_XUARTPS_0_CLOCK_HZ
#define UART_DEVICE_ID XPAR_XUARTPS_0_DEVICE_ID
#define TEST_BUFFER_SIZE 16
int UartPsEchoExample(u32 UartBaseAddress,u16 DeviceId);
/************************** Variable Definitions ***************************/
XUartPs Uart_Ps; /* The instance of the UART Driver */
u8 SendBuffer[TEST_BUFFER_SIZE]; /* Buffer for Transmitting Data */
int main(void)
{
int Status;
/*
* Run the Uart Echo example , specify the Base Address that is
* generated in xparameters.h
*/
Status = UartPsEchoExample(UART_BASEADDR, UART_DEVICE_ID);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/**************************************************************************/
/**
*
* This function does a minimal test on the UART device using the hardware
* interface.
*
* #param UartBaseAddress is the base address of the device
*
* #return XST_SUCCESS if successful, XST_FAILURE if unsuccessful
*
* #note None.
*
**************************************************************************/
int UartPsEchoExample(u32 UartBaseAddress,u16 DeviceId)
{
int Index;
u32 Running;
u32 CntrlRegister;
int Status;
union {
float float_variable;
u8 bytes_array[4];
} input,output;
// Overwrite bytes of union with float variable
int recvCount=0;
XUartPs_Config *Config;
/*
* Initialize the UART driver so that it's ready to use
* Look up the configuration in the config table and then initialize it.
*/
Config = XUartPs_LookupConfig(DeviceId);
if (NULL == Config) {
return XST_FAILURE;
}
Status = XUartPs_CfgInitialize(&Uart_Ps, Config, Config->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
XUartPs_SetBaudRate(&Uart_Ps, 115200);
CntrlRegister = XUartPs_ReadReg(UartBaseAddress, XUARTPS_CR_OFFSET);
/* Enable TX and RX for the device */
XUartPs_WriteReg(UartBaseAddress, XUARTPS_CR_OFFSET,
((CntrlRegister & ~XUARTPS_CR_EN_DIS_MASK) |
XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN));
/*
* Initialize the send buffer bytes with a pattern to send and the
* the receive buffer bytes to zero
*/
for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {
SendBuffer[Index] = Index + '0';
}
/* Send the entire transmit buffer. */
for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {
/* Wait until there is space in TX FIFO */
while (XUartPs_IsTransmitFull(UartBaseAddress));
/* Write the byte into the TX FIFO */
XUartPs_WriteReg(UartBaseAddress, XUARTPS_FIFO_OFFSET,
SendBuffer[Index]);
}
Running = TRUE;
while (Running) {
/* Wait until there is data */
while (!XUartPs_IsReceiveData(UartBaseAddress));
while(recvCount<4)
{
input.bytes_array[recvCount]=XUartPs_RecvByte(UartBaseAddress);
//XUartPs_Recv(&Uart_Ps, &u.temp_array[recvCount], 1);
recvCount++;
}
recvCount=0;
}
return XST_SUCCESS;
}
I am implementing a simple canbus communication using the K66F micro controller which has a CAN0 and CAN1 buses. The goal is to send a message from CAN0 to CAN1.
I am using the example code provided by NXP for the from K66F board. The problem is that when using a logic analyzer, I can see that the message is sent and acknowledged but the program gets stuck at !rxcomplete, even though I can clearly see that the message has been acknowledged. Therefore I assume I have some configuration parameter not set properly.
I don't know if the parameters i have are the correct. The electronic wiring i think its fine according to the messages sent.
this is the code I'm using:
#include "fsl_debug_console.h"
#include "fsl_flexcan.h"
#include "board.h"
#include "pin_mux.h"
#include "clock_config.h"
/****************************************************************************
* Definitions
***************************************************************************/
#define EXAMPLE_CAN CAN0
#define EXAMPLE_CAN1 CAN1
#define EXAMPLE_CAN_CLKSRC1 kCLOCK_BusClk
#define EXAMPLE_CAN_CLKSRC kCLOCK_BusClk
#define RX_MESSAGE_BUFFER_NUM (8)
#define TX_MESSAGE_BUFFER_NUM (9)
/***************************************************************************
* Prototypes
*****************************************************************************/
/***************************************************************************
* Variables
***************************************************************************/
volatile bool txComplete = false;
volatile bool rxComplete = false;
flexcan_handle_t flexcanHandle;
flexcan_mb_transfer_t txXfer, rxXfer;
flexcan_frame_t txFrame, rxFrame;
int status;
/***************************************************************************
* Code
***************************************************************************/
/*!
* #brief FlexCAN Call Back function
*/
static void flexcan_callback(CAN_Type *base, flexcan_handle_t *handle, status_t status, uint32_t result, void *userData)
{
switch (status)
{
/* Process FlexCAN Rx event. */
case kStatus_FLEXCAN_RxIdle:
PRINTF("prueba \n");
if (RX_MESSAGE_BUFFER_NUM == result)
{
rxComplete = true;
}
break;
/* Process FlexCAN Tx event. */
case kStatus_FLEXCAN_TxIdle:
if (TX_MESSAGE_BUFFER_NUM == result)
{
txComplete = true;
}
break;
default:
break;
}
/*!
* #brief Main function
*/
int main(void)
{
flexcan_config_t flexcanConfig;
flexcan_rx_mb_config_t mbConfig;
/* Initialize board hardware. */
BOARD_InitPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();
PRINTF("\r\n==FlexCAN loopback example -- Start.==\r\n\r\n");
/* Init FlexCAN module. */
/*
* flexcanConfig.clkSrc = kFLEXCAN_ClkSrcOsc;
* flexcanConfig.baudRate = 125000U;
* flexcanConfig.maxMbNum = 16;
* flexcanConfig.enableLoopBack = false;
* flexcanConfig.enableSelfWakeup = false;
* flexcanConfig.enableIndividMask = false;
* flexcanConfig.enableDoze = false;
*/
FLEXCAN_GetDefaultConfig(&flexcanConfig);
flexcanConfig.clkSrc = kFLEXCAN_ClkSrcPeri;
//flexcanConfig.enableLoopBack = true;
flexcanConfig.baudRate = 125000U;
FLEXCAN_Init(EXAMPLE_CAN, &flexcanConfig, CLOCK_GetFreq(EXAMPLE_CAN_CLKSRC));
FLEXCAN_Init(EXAMPLE_CAN1, &flexcanConfig, CLOCK_GetFreq(EXAMPLE_CAN_CLKSRC));
/* Setup Rx Message Buffer. */
mbConfig.format = kFLEXCAN_FrameFormatStandard;
mbConfig.type = kFLEXCAN_FrameTypeData;
mbConfig.id = FLEXCAN_ID_STD(0x223);
FLEXCAN_SetRxMbConfig(EXAMPLE_CAN1, RX_MESSAGE_BUFFER_NUM, &mbConfig, true);
/* Setup Tx Message Buffer. */
FLEXCAN_SetTxMbConfig(EXAMPLE_CAN, TX_MESSAGE_BUFFER_NUM, true);
/* Create FlexCAN handle structure and set call back function. */
FLEXCAN_TransferCreateHandle(EXAMPLE_CAN, &flexcanHandle, flexcan_callback, NULL);
//FLEXCAN_TransferCreateHandle(EXAMPLE_CAN1, &flexcanHandle, flexcan_callback, NULL);
/* Start receive data through Rx Message Buffer. */
rxXfer.frame = &rxFrame;
rxXfer.mbIdx = RX_MESSAGE_BUFFER_NUM;
FLEXCAN_TransferReceiveNonBlocking(EXAMPLE_CAN1, &flexcanHandle, &rxXfer);
PRINTF("status=%d \n", status);
/* Prepare Tx Frame for sending. */
txFrame.format = kFLEXCAN_FrameFormatStandard;
txFrame.type = kFLEXCAN_FrameTypeData;
txFrame.id = FLEXCAN_ID_STD(0x223);
txFrame.length = 8;
txFrame.dataWord0 = CAN_WORD0_DATA_BYTE_0(0x11) | CAN_WORD0_DATA_BYTE_1(0x22) | CAN_WORD0_DATA_BYTE_2(0x33) |
CAN_WORD0_DATA_BYTE_3(0x44);
txFrame.dataWord1 = CAN_WORD1_DATA_BYTE_4(0x55) | CAN_WORD1_DATA_BYTE_5(0x66) | CAN_WORD1_DATA_BYTE_6(0x77) |
CAN_WORD1_DATA_BYTE_7(0x88);
PRINTF("Send message from MB%d to MB%d\r\n", TX_MESSAGE_BUFFER_NUM, RX_MESSAGE_BUFFER_NUM);
PRINTF("tx word0 = 0x%x\r\n", txFrame.dataWord0);
PRINTF("tx word1 = 0x%x\r\n", txFrame.dataWord1);
/* Send data through Tx Message Buffer. */
txXfer.frame = &txFrame;
txXfer.mbIdx = TX_MESSAGE_BUFFER_NUM;
FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
while ((!txComplete))
{
};
PRINTF("tx complete \n");
/* Waiting for Rx Message finish. */
while ((!rxComplete))
{
};
PRINTF("\r\nReceved message from MB%d\r\n", RX_MESSAGE_BUFFER_NUM);
PRINTF("rx word0 = 0x%x\r\n", rxFrame.dataWord0);
PRINTF("rx word1 = 0x%x\r\n", rxFrame.dataWord1);
/* Stop FlexCAN Send & Receive. */
FLEXCAN_TransferAbortReceive(EXAMPLE_CAN1, &flexcanHandle, RX_MESSAGE_BUFFER_NUM);
FLEXCAN_TransferAbortSend(EXAMPLE_CAN, &flexcanHandle, TX_MESSAGE_BUFFER_NUM);
PRINTF("\r\n==FlexCAN loopback example -- Finish.==\r\n");
while (1)
{
__WFI();
}
}
this is what i can read with the logic analyzer:
}
Thank you in advance.
Callback should be enabled for CAN1 to set rxComplete = true;.