1

I am reading the source code of a UART peripheral and there is a function as below:

eResult = adi_stdio_ControlDevice (hSTDIOUART,
    ADI_STDIO_COMMAND_SET_UART_BAUD_RATE, (void *)57600);

This function is used to connect UART and number 57600 is the baudrate. What I do not understand is the meaning of (void*)57600.

I think this maybe a pointer to const and the return value of (void*)57600 is 57600. When we use (void*)57600, does it mean we are creating a pointer that points to the 57600 value?

And why we must use (void*)57600?

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
Thanh Nguyen
  • 45
  • 1
  • 7

1 Answers1

2

Not quite. The "return value" (quoted because it's not actually being returned from a function, instead it's the result of a cast) of (void *)57600 is simply the value 57600 being treated as (or, in other words, cast to) a void pointer.

And, while you are actually converting 57600 to a void pointer, it's almost certainly not being used as a pointer. More likely is that the prototype for adi_stdio_ControlDevice has a generic argument (one that can be used for many things).

Device control functions are particularly apt to do that since they are meant to be generic across a large variety of devices, so you may have to give a wide variety of types to the calls.

You'll probably find that, for the command to set the baud rate, it simply gets cast back to an integral value at the other end before being used, something like:

static int localSpeed;
static char *localString;
static double localPi;
static struct rational { int numerator; int denominator } localStruct;

bool adi_stdio_ControlDevice (HANDLE hndl, COMMAND cmd, void *generic) {
    switch (cmd) {
        case ADI_STDIO_COMMAND_SET_UART_BAUD_RATE: {
            localSpeed = (int)generic;
            break;
        }
        case ADI_COMMAND_WITH_STRING_ARG: {
            if (localString) free(localString);
            localString = strdup((char*)generic);
            break;
        }
        case ADI_COMMAND_WITH_DOUBLE_PTR_ARG: {
            localPi = *((double*)generic));
            break;
        }
        case ADI_COMMAND_WITH_STRUCT_PTR: {
            memcpy(localStruct, generic, sizeof(localStruct));
            break;
        }
    }
}

Other commands (such as the fake ones I've added) would be able to use the generic argument in a variety of ways, as integers or other pointer types for example.


This is actually supported by the documentation (VisualDSP++ 5.0 Device Drivers and System Services Manual for Blackfin® Processors) for that call, which states:

 ADI_STDIO_RESULT adi_stdio_ControlDevice (
   ADI_STDIO_DEVICE_HANDLE hStdioDevice,
   uint32_t nCommandID,
   void *const pValue
 );
 : : :
pValue: Argument required for executing the command. Depending upon the command, different types of arguments are required.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • Thank you. So as i understanding, we have to use (void*)57600 beacause the input of adi_stdio_ControlDevice() need a void *const. Now i am wondering what is type casting actually do in C. If i write (void*) 57600, so it will change data type of 57600 from something (i do not know because it is constant) to a void pointer (4 byte with 32 bit system). Is this true ? And in the virtual memory allocation of C, there will be two memory are, one is used for const 57600 and one is used for pointer voide* 57600 ? (this seem not true). – Thanh Nguyen Dec 17 '19 at 07:26
  • Yes, @Lundin, it's not the best, it's just the way they chose it to allow any type of argument. From memory, the UNIX/Linux `ioctl()`is very similar. – paxdiablo Dec 17 '19 at 12:28
  • @Thanh, `(void*)N` doesn't really create another "thing", it rather just treats `N` as if it were a void pointer. Similar to `(float) 1 / 3` which would do floating point division (to get `0.33`-ish) because you're treating the integer `1` as a float rather than an integer (`1 / 3` would truncate to zero because it's integer division). – paxdiablo Dec 17 '19 at 12:31
  • i have read document "VisualDSP++ 5.0 Device Drivers and System Services Manual for Blackfin® Processors", there are many helpful API function, but i do not want to use API function because i could help me to actually understand about how chip works. Could you recommend me some document or example, web,...etc which program blackfin chip by register value? – Thanh Nguyen Dec 20 '19 at 07:39