FTDI Community

Please login or register.

Login with username, password and session length.
Advanced Search  

News:

Welcome to the FTDI Community!

Please read our Welcome Note

Technical Support enquires
please contact the team
@ FTDI Support


New Bridgetek Community is now open

Please note that we have created the Bridgetek Community to discuss all Bridgetek products e.g. EVE, MCU.

Please follow this link and create a new user account to get started.

Bridgetek Community

Show Posts

You can view here all posts made by this member. Note that you can only see posts made in areas to which you currently have access.

Messages - KTrenholm

Pages: [1]
1
Hello,

Ok that's fine then.

using the BOMS and FAT files to detect connection/removal won't work. As you say the UART2DSC doesn't do anything to detect removal or connection of USB devices. This is because it is a minimum project that is used to demonstrate how to write to a file on a flash disk. the procedure is as follows:

the USB host call to VOS_IOCTL_USBHOST_GET_CONNECT_STATE to see if there is a device connected and enumerated.
Search through the devices for the correct device.
Then open and attach the BOMS driver to the handle to the correct device.
After that attach the FAT driver to the BOMS driver.

Periodically poll the VOS_IOCTL_USBHOST_GET_CONNECT_STATE for disconnection, this checks that a device is connected to the root hub.
Also check the return value of any FAT or BOMS driver calls for FAT_NOT_FOUND or FAT_ERROR/FAT_FATAL_ERROR, MSI_NOT_FOUND or other errors. If there is an error again check VOS_IOCTL_USBHOST_GET_CONNECT_STATE to confirm or if there is a bub involved

On disconnection, detach FAT then BOMS drivers from the device.

I would recommend you use one of our other projects such as V2DAP, which has increased functionality and can be downloaded here: https://ftdichip.com/firmware/precompiled/.

Best Regards

FTDI Community

Thanks for this!  I've been sidetracked to another project for the moment but will be sure to give this a try when I get the chance ;D.

2
Hello,

Sorry for the misunderstanding.

what version of the VNC2 toolchain are you using?

version V2.0.2-SP2 fixes a known connect/disconnect issue.

Download Vinculum II Toolchain V2.0.2-SP2

let me know if you are already using this version.

Best regards

FTDI community

I am on v2.0.2 SP3 (received from FTDI support last week).

3
Hi FTDI Community,

I think there's a misunderstanding what I'm trying to do?  Those AppNotes are for using the VNC2 as a USB Device(Slave) while I am looking to use the VNC2 as a USB Host.  I'm looking to detect and handle the connection/disconnection of a USB Flash Drive to the VNC2 USB Host. 
The AN and sample firmware I am using as a base is:
https://ftdichip.com/wp-content/uploads/2020/08/AN_187_Vinculum-II_UART_to_USB_Memory_Bridge.pdf

This firmware however only detects connection of the USB Memory device on VNC2 power-up and will loop looking for a USB device until one is detected and enumerated.  It does not support removal or reconnection of the USB Memory device after it has been removed.  That is the functionality I'm trying to add.  There does not appear to be a specific AppNote for this case.

I'm thinking I can use a timer to periodically check for connect/disconnect, but I am unclear on what exactly must be re-initialized/un-initialized when a USB Memory device is reconnected/disconnected.  Is just Attaching/Detaching the BOMS and FAT enough?  Do BOMS and FAT need to be completely shut down and reinitialized?

4
Hello!

I'm looking to devise a way to handle connection and disconnection of a USB Flash Drive using the UART2DSC project as a base.  I wanted to ask a couple questions regarding what would be the "clean" way to handle such a thing?

My thought is to use a timer and essentially poll the USB host connection status every 250ms or so and act upon that.  The device configuration and timer thread looks like this:

Code: [Select]
vos_tcb_t *tcbPOLL_USB;
VOS_HANDLE hTIMER; //USB Poll Timer

void POLL_USB();

void main(void){
    // USB Host configuration context
    usbhost_context_t usbhostContext;
    //TIMER Configuration context
    tmr_context_t timerContext;

    // Initialise FAT File System Driver
    fatdrv_init(VOS_DEV_FAT_FILE_SYSTEM);

    // Initialise BOMS Device Driver
    boms_init(VOS_DEV_BOMS);

    // Initialise USB Host
    usbhostContext.if_count = 8;
    usbhostContext.ep_count = 16;
    usbhostContext.xfer_count = 2;
    usbhostContext.iso_xfer_count = 2;
    usbhost_init(VOS_DEV_USBHOST_1, -1, &usbhostContext);

    //Initialise Timer0 - USB Poll Device Status - Connect/Disconnect
    timerContext.timer_identifier = TIMER_0;
    tmr_init(TIMER_0, &timerContext);
    tcbPOLL_USB = vos_create_thread_ex(24, 256, POLL_USB, "PollUSB", 0);

    /*Snipped - Other Device Config*/

    vos_start_scheduler();
}

//POLL_USB TIMER THREAD
void POLL_USB(){
    tmr_ioctl_cb_t tmr_iocb;
    uint8_t usb_connstate;
    static uint8_t usb_connstate_prev = PORT_STATE_DISCONNECTED;

    hTIMER = vos_dev_open(TIMER0);

    tmr_iocb.ioctl_code = VOS_IOCTL_TIMER_SET_TICK_SIZE;
    tmr_iocb.param = TIMER_TICK_MS;
    vos_dev_ioctl(hTIMER,&tmr_iocb);

    tmr_iocb.ioctl_code = VOS_IOCTL_TIMER_SET_COUNT;
    tmr_iocb.param = 250;
    vos_dev_ioctl(hTIMER,&tmr_iocb);

    vos_iocb.ioctl_code = VOS_IOCTL_TIMER_SET_MODE;
    tmr_iocb.param = TIMER_MODE_CONTINUOUS;
    vos_dev_ioctl(hTIMER,&tmr_iocb);

    tmr_iocb.ioctl_code = VOS_IOCTL_TIMER_START;
    vos_dev_ioctl(hTIMER,&tmr_iocb);

    while (1){
        tmr_iocb.ioctl_code = VOS_IOCTL_TIMER_WAIT_ON_COMPLETE;
vos_dev_ioctl(hTIMER, &tmr_iocb);

usb_connstate = usbhost_connect_state(hUSBHOST_1);

if (usb_connstate == PORT_STATE_DISCONNECTED){

    if (usb_connstate_prev != PORT_STATE_DISCONNECTED){
                //Connected -> Disconnected --Detach BOMS and FAT File System
        boms_detach(hBOMS);
fat_detach(hFAT_FILE_SYSTEM);

    }

}

if (usb_connstat == PORT_STATE_ENUMERATED){

    if (usb_connstate_prev != PORT_STATE_ENUMERATED){
                //Un-enumerated -> Enumerated --Attach BOMS and FAT File system
hBOMS = boms_attach(hUSBHOST_1, VOS_DEV_BOMS);
hFAT_FILE_SYSTEM = fat_attach(hBOMS, VOS_DEV_FAT_FILE_SYSTEM);

//attach the stdio file system to the FAT file system
fsAttach(hFAT_FILE_SYSTEM);
     }

}

        usb_connstate_prev = usb_connstate;
    }

}

Would it all be just as simple at this above?  Do I have to do anything extra to cleanly detach the BOMS and FAT when the device has been removed?  Would I need to re-initialize them via their respective init_ functions or is detach/attach functions adequate after the initial init_ calls at the start of main()?  Is the call to fsAttach necessary after a disconnect/reconnect? or should I only call that once on initialization?

5
If it's OK I'm just going to drop another curiosity I came across here in hopes it might save others some time if they come across something similar.

This I found when transitioning my code over to Release from Debug.  Seems to occur when any kind of optimization level >0 is applied.  Works correctly on Level 0.

Consider the following implementation of fgets():
Code: [Select]
char * fgets(char *dst, int max, FILE *fp)
{
int c;
char *p;
int eof;

/* get max bytes or upto a newline */
for (p = dst, max--; max > 0; max--) {

c = fgetc(fp);

if ((eof = feof(fp)) != 0)
break;
*p++ = c;
if (c == '\n')
break;
}
*p = 0;

if (p == dst || eof != 0)
return NULL;
return (p);
}

What I found was with any optimization (any level >0) this would continue reading past the newline 0x0A character and continue until max is hit.
Changing the type of the c variable from:
Code: [Select]
int c;over to:
Code: [Select]
unsigned char c;solves the issue and it now the if statement works as intended and breaks on the newline character, but now I have an annoying warning that there is a return type mismatch on the fgetc() call, since according to the prototype in stdio.h, it returns an int.  To quiet that down, I tried going back to declaring c as an int, then casting c to uint8_t (unsigned char) for the if() statement:
Code: [Select]
if ((uint8_t)c == '\n')and this seems to work alright.  Must be something to do with how it tries to optimize the comparison between a int (signed 32-bit) and a signed or unsigned (I saw the same behavior when I used 0x0A instead of '\n') 8-bit literal.  My ASM is probably much too rusty to really dig through the compiled asm code to pinpoint it so I'll just leave it at that I suppose.




6
Hi
Did you try hitting “Pause” in the debug ribbon?
Calculating the peak stack is transfer intensive so I’d bet it would only be performed when it’s stopped running the actual code on the device. 

Regards
FTDI Community

Aha, that looks to have done it (it appeared when I hit a breakpoint), not sure how I missed that, thanks!

7
Hi,
Can you provide some screen shots of the issue you are seeing? 
Build settings (Debug/Release) ?   
How big are the stacks for each thread?
Maybe the scheduler has not started? That would need to be running to get the thread manager to show information.
Does it have the current stack size listed?

Regards
FTDI Community

- Build is set for Debug.
- I have 5 application threads, configured as follows:
Code: [Select]
tcbSETUP = vos_create_thread_ex(25, 1024, setup, "Setup", 0);
tcbUART = vos_create_thread_ex(24, 1024, UART, "UART", 0);
tcbBOOTL = vos_create_thread_ex(24, 2048, BOOTL, "BOOTLOAD", 0);
tcbBOMS_RD = vos_create_thread_ex(25, 2048, BOMS_RD, "BOMSRead", 0);
tcbCOMMAND = vos_create_thread_ex(24, 512, COMMAND, "Command", 0);
Some of these may be a little larger than needed in terms of stack size, but that's why I'm looking for the max stack usage.

-Screen capture of the Thread Manager is attached (not sure how to inline in my post).  All information is present other than Peak Stack.




8
Interesting, good to know w/ regard to the casts.

I ended up just defining the table on a different microcontroller and snooped the values with the debugger tool.  Here's the table I ended up with in hex (looks to line up with your decimal equivalents):
Code: [Select]
static const uint32_t table[16] =
    {
        0,                    (uint32_t)0x105EC76F, (uint32_t)0x20BD8EDE, (uint32_t)0x30E349B1,
        (uint32_t)0x417B1DBC, (uint32_t)0x5125DAD3, (uint32_t)0x61C69362, (uint32_t)0x7198540D,
        (uint32_t)0x82F63B78, (uint32_t)0x92A8FC17, (uint32_t)0xA24BB5A6, (uint32_t)0xB21572C9,
        (uint32_t)0xC38D26C4, (uint32_t)0xD3D3E1AB, (uint32_t)0xE330A81A, (uint32_t)0xF36E6F75,
    };


9
Hello,

I'm debugging a project in the Vinculum II IDE using a V2EVAL kit with the VNC2 48-pin Daughterboard.
I notice that the Thread Manager window has a column for Peak Stack (Bytes), but it is not populating with any information (all other columns show data, including Current Stack).

Has anyone come across this before?  Something I need to set somewhere maybe?

Thanks!

10
So here's a question regarding the stdio library.  I need to use fgets() which is noted in stdio.h as "To Be Added".  So let's put one in.  The fgets() implementation I'm using makes use of fgetc(), which is implemented in stdio.  However I can't find a reference for the EOF return value?  I need to check for EOF on the fgetc() call.  I know normally (in most implementations at least?) EOF == -1, but I'm not about to take that as gospel just because that's how it works in GCC, as the C standard says it can be implementation defined.  Would anyone be able to confirm what fgetc() returns when the end of file is encountered?  Is the FAT_EOF enum what I should be using?
[EDIT] I was able to rather than use the return value of fgetc() with any kind of EOF value use the feof() function to determine end of file and it seems to work

Oh, and a new bit of fun, I had to also put an implementation of strcspn() in, and the compiler does not much care for assigning pointers in the declaration:
Code: [Select]
static size_t strcspn(const char * s1, const char * s2){
    char *s = s1;    //Error C2808 illegal use of pointer
    char *c;

    while (*s1)
    {
        for (c = s2; *c; c++)
{
    if (*s1 == *c)
        break;
}

        if (*c)
    break;
s1++;
    }

    return s1 - s;

}

moving the assignment after the declaration clears it up:
Code: [Select]
static size_t strcspn(const char * s1, const char * s2){
    char *s;   
    char *c;

    *s = s1;    //No Errors Thrown!

    while (*s1)
    {
        for (c = s2; *c; c++)
        {
            if (*s1 == *c)
    break;
        }

        if (*c)
    break;
        s1++;
    }

    return s1 - s;

}

11
Indeed, changed "address" to "addr" and it cleared it right up.  I would expect the editor in the IDE to color it like a type if it was reserved by the toolchain in some way.  Time to do a whole lot of find/replace, as you can imagine for a bootloader, the name address is everywhere.

I don't know if I would have ever considered the name "address" being the problem!
Thanks for the tip!

(P.S. There is no mention of "address" being a reserved word/type in AN151 - Vinculum-II User's Guide, at least not that I could find.  Worth noting this does not seem to be documented anywhere)

I also found something else weird.  VinC will not compile this CRC32 table:
Code: [Select]

    enum {
        g0 = 0x82F63B78,
        g1 = (g0 >> 1) & 0x7fffffff,
        g2 = (g0 >> 2) & 0x3fffffff,
        g3 = (g0 >> 3) & 0x1fffffff,
    };

    static const uint32_t table[16] =
    {
        0,                  (uint32_t)g3,           (uint32_t)g2,           (uint32_t)(g2^g3),
        (uint32_t)g1,       (uint32_t)(g1^g3),      (uint32_t)(g1^g2),      (uint32_t)(g1^g2^g3),
        (uint32_t)g0,       (uint32_t)(g0^g3),      (uint32_t)(g0^g2),      (uint32_t)(g0^g2^g3),
        (uint32_t)(g0^g1),  (uint32_t)(g0^g1^g3),   (uint32_t)(g0^g1^g2),   (uint32_t)(g0^g1^g2^g3),
    };

This throws (error) C2001 expression not constant for every element in that table that isn't 0 or g0.  All elements in the table should be calculable at compile-time (ARM-GCC and MSVC++ have no problems).  At the end of the day I can calculate these all out in another compiler or even just through a programmers calculator and put the constants into my VNC2 project.  Still, kind of a pain.

EDIT: found this in the Toolchain ReadMe, sounds like what I was running into:
Quote
Restrictions:
- Floating point not supported.
- Structs and unions may not be passed to or returned from a function. Pointers to structs and unions are allowed.
- Vacuous declarations of structures and unions is not supported.
- Structure and union assignments not supported.
- Anonymous aggregates, unnamed members in unions, are not supported.
- Compound literals expressions are not supported.
- Modulus operations treat signed values as unsigned values. Do not use with negative values.
I'd imagine those table entries are "Compound literal expressions"?

12
Discussion - Software / Vinculum II Toolchain (VinC) Issues Porting Code
« on: October 18, 2021, 04:49:15 PM »
Hey all,

I'm working on a project to turn the VNC2 into essentially a bootloader host for a Cypress PSoC5LP.  The idea being to connect a USB flash drive to the system, read the firmware file, and bootload the MCU via the UART.

This would in theory not be too much trouble, as Cypress actually provides the C (I think GCC) code for a bootloader host for use in this exact kind of situation.  I figured porting the bootloader host wouldn't be too tall of an order.  However I am running into problems with VinC throwing some unexpected syntax errors.

First thing I noticed what was that the toolchain appears to have no stdint.h?  Since all the bootloader host code is written with standard types like uint8_t/uint16_t/uint32_t I just needed a few typedefs.  I included my own header file to provide the needed types and replaced the includes of stdint.h with my own little "int.h":

Code: [Select]
#ifndef _INT_H_
#define _INT_H_

typedef signed char int8_t;
typedef signed short int16_t;
typedef signed long int32_t;

typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;

#endif

No problems so far, I get a few warnings for mismatched widths/signs on certain calls but I can resolve those easily enough.
The real weirdness starts with the C1000 errors I'm getting:
..\cybootloaderutils\cybtldr_api.c line 401: (error) C1000 syntax error, unexpected TYPE_NAME
..\cybootloaderutils\cybtldr_api.c line 423: (error) C1000 syntax error, unexpected TYPE_NAME
..\cybootloaderutils\cybtldr_api.c line 456: (error) C1000 syntax error, unexpected TYPE_NAME


I'm not sure where these are cropping up from.  Here's the function with the call that causes the first C1000 error:
Code: [Select]
int CyBtldr_ProgramRow_v1(uint32_t address, uint8_t* buf, uint16_t size)
{
    const int TRANSFER_HEADER_SIZE = 15;

    uint8_t inBuf[MAX_COMMAND_SIZE];
    uint8_t outBuf[MAX_COMMAND_SIZE];
    uint32_t inSize;
    uint32_t outSize;
    uint16_t offset = 0;
    uint16_t subBufSize;
    uint8_t status = CYRET_SUCCESS;
    int err = CYRET_SUCCESS;

    uint32_t chksum = CyBtldr_ComputeChecksum32bit(buf, size);

    if (CYRET_SUCCESS == err)
        err = SendData(buf, size, &offset, (uint16_t)(g_comm->MaxTransferSize - TRANSFER_HEADER_SIZE), inBuf, outBuf);

    if (CYRET_SUCCESS == err)
    {
        subBufSize = (uint16_t)(size - offset);

        err = CyBtldr_CreateProgramDataCmd(address, chksum, &buf[offset], subBufSize, inBuf, &inSize, &outSize);    //401 - C1000 syntax error: unexpected TYPE NAME
        if (CYRET_SUCCESS == err)
            err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize);
        if (CYRET_SUCCESS == err)
            err = CyBtldr_ParseDefaultCmdResult(outBuf, outSize, &status);
        if (CYRET_SUCCESS != status)
            err = status | CYRET_ERR_BTLDR_MASK;
    }

    return err;
}

The code for the function in question is here:
Code: [Select]
int CyBtldr_CreateProgramDataCmd(uint32_t address, uint32_t chksum, uint8_t* buf, uint16_t size, uint8_t* cmdBuf, uint32_t* cmdSize, uint32_t* resSize)
{
    const uint16_t COMMAND_DATA_SIZE = 8;
    uint16_t i;
    *resSize = BASE_CMD_SIZE;
    *cmdSize = BASE_CMD_SIZE + COMMAND_DATA_SIZE + size;

    fillData32(cmdBuf + 4, address);
    fillData32(cmdBuf + 8, chksum);
    for (i = 0; i < size; i++)
        cmdBuf[i + 4 + COMMAND_DATA_SIZE] = buf[i];
    return  CreateCmd(cmdBuf, *cmdSize, CMD_PROGRAM_DATA);
}


I'm kind of at a loss as to where an unexpected TYPE_NAME could be coming up.  If it was an issue with my typedefs, I'd think this error would be cropping up in many more places.

Here are the other places this error is thrown:
Code: [Select]
int CyBtldr_EraseRow_v1(uint32_t address)
{
    uint8_t inBuf[MAX_COMMAND_SIZE];
    uint8_t outBuf[MAX_COMMAND_SIZE];
    uint32_t inSize = 0;
    uint32_t outSize = 0;
    uint8_t status = CYRET_SUCCESS;
    int err = CYRET_SUCCESS;

    if (CYRET_SUCCESS == err)
        err = CyBtldr_CreateEraseDataCmd(address, inBuf, &inSize, &outSize);    //423 - C1000 syntax error: unexpected TYPE NAME
    if (CYRET_SUCCESS == err)
        err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize);
    if (CYRET_SUCCESS == err)
        err = CyBtldr_ParseEraseRowCmdResult(outBuf, outSize, &status);
    if (CYRET_SUCCESS != status)
        err = status | CYRET_ERR_BTLDR_MASK;

    return err;
}


int CyBtldr_VerifyRow_v1(uint32_t address, uint8_t* buf, uint16_t size)
{
    const int TRANSFER_HEADER_SIZE = 15;

    uint8_t inBuf[MAX_COMMAND_SIZE];
    uint8_t outBuf[MAX_COMMAND_SIZE];
    uint32_t inSize;
    uint32_t outSize;
    uint16_t offset = 0;
    uint16_t subBufSize;
    uint8_t status = CYRET_SUCCESS;
    int err = CYRET_SUCCESS;

    uint32_t chksum = CyBtldr_ComputeChecksum32bit(buf, size);

    if (CYRET_SUCCESS == err)
        err = SendData(buf, size, &offset, (uint16_t)(g_comm->MaxTransferSize - TRANSFER_HEADER_SIZE), inBuf, outBuf);

    if (CYRET_SUCCESS == err)
    {
        subBufSize = (uint16_t)(size - offset);

        err = CyBtldr_CreateVerifyDataCmd(address, chksum, &buf[offset], subBufSize, inBuf, &inSize, &outSize);    //456 - C1000 syntax error: unexpected TYPE NAME
        if (CYRET_SUCCESS == err)
            err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize);
        if (CYRET_SUCCESS == err)
            err = CyBtldr_ParseDefaultCmdResult(outBuf, outSize, &status);
        if (CYRET_SUCCESS != status)
            err = status | CYRET_ERR_BTLDR_MASK;
    }

    return err;
}

Might anyone have an idea as to why this specific error is being thrown (or how to resolve it)?

Pages: [1]