
En la vida de cada cajón, llega un momento en que desea escribir su propio cargador del archivo de configuración en el FPGA. Tuve que participar en el desarrollo de un stand de capacitación para el departamento de una universidad técnica. El soporte está diseñado para estudiar el procesamiento de señales digitales, aunque esto no es de particular importancia en el marco de este artículo. Y lo importante es que el FPGA (Altera Cyclone IV) está en el centro del stand, en el que los estudiantes recopilan todo tipo de esquemas DSP, tal como los concibió el autor del stand. El soporte está conectado a la computadora a través de USB. Necesita descargar el FPGA de la computadora a través de USB.
Se tomó la decisión de conectarse a una PC usando FTDI en su encarnación de doble canal: FT2232H. Un canal se usará para la configuración de FPGA, el otro se puede usar para el intercambio FIFO de alta velocidad.
FTDI tiene una placa de depuración MORPH-IC-II , donde el FPGA Cyclone II se flashea a través de USB. Conceptos en el dominio público. El código fuente del gestor de arranque está parcialmente abierto: el gestor de arranque está disponible, sin embargo, toda la lógica de trabajar con FTDI se traslada a una biblioteca privada y no se puede modificar. En verdad, originalmente planeé usar este gestor de arranque en mi proyecto o, en casos extremos, hacer que mi shell se base en su dll. El firmware se carga en el FPGA en modo serie pasivo (serie pasiva - PS), FTDI funciona en modo MPSSE. En el tablero, el rendimiento de la solución MORPH-IC-II se confirmó por completo, pero el problema, como suele suceder, no vino de dónde. Resultó que durante la operación del dll MORPH-IC-II, todos los dispositivos FTDI conectados están bloqueados, y como parte del complejo de entrenamiento hay dos dispositivos más con convertidores similares: un generador y un analizador de señal. El trabajo simultáneo con ellos no es posible. Maldita sea raro y molesto.
Un caso similar fue implementado por los chicos del rover Mars: el programador USB JTAG MBFTDI . FTDI también se usa allí en modo MPSSE, pero a diferencia de MORPH-IC-II, las operaciones FPGA se realizan en modo JTAG. Las fuentes están disponibles gratuitamente, pero no encontré una indicación clara de su estado (licencia). Por lo tanto, para usarlos en un proyecto comercial, mi mano no se levantó.
Corregiré tal error, todo lo que se presentará en el marco de este artículo se publica en un repositorio abierto bajo la licencia BSD.
Descargar el archivo de configuración al chip FPGA
En primer lugar, debe tratar con el modo de arranque FPGA. Para aquellos que recién están comenzando a familiarizarse con el tema, les daré una pequeña excursión. Aunque los FPGA Altera (Intel) de la familia Cyclone IV E están instalados en mi placa, los métodos de carga son similares para todo el grupo Cyclone FPGA, y existe la sospecha de que de una forma u otra son adecuados para muchas otras familias.
Este tipo de FPGA utiliza SRAM volátil para almacenar datos de configuración. Estos datos de configuración determinan la funcionalidad del dispositivo resultante. En la jerga profesional, estos datos a menudo se denominan "firmware". Por lo tanto, el firmware se almacena en una RAM especial y cada vez que se enciende el dispositivo, debe cargarse en el chip FPGA. Hay varias formas (esquemas de configuración) por las cuales el firmware se puede cargar en SRAM (la lista es relevante para el Ciclón IV E):
- Serie activa (AS).
- Paralelo activo (AP)
- Serie pasiva (PS)
- Paralelo pasivo rápido (FPP).
- JTAG
La elección de un modo de arranque específico se realiza utilizando los terminales externos del FPGA (grupo MSEL). El modo JTAG siempre está disponible. El modo activo implica que cuando se aplica energía, el FPGA lee de forma independiente los datos de la memoria externa (en serie o en paralelo). En modo pasivo, el FPGA espera a que un medio externo le transfiera proactivamente los datos de configuración. Estos esquemas encajan bien en el concepto de maestro (maestro) - esclavo (esclavo). En modos activos, el FPGA actúa como maestro y en modos pasivos como esclavo.
En este problema, no es el FPGA, pero el usuario debe decidir cuándo se debe actualizar el firmware, por lo que el modo de arranque debe ser pasivo. Y para salvar las patas del chip, elegimos una interfaz en serie. El modo serie pasivo (PS) y JTAG son adecuados aquí. La lógica del JTAG es algo más complicada, así que centrémonos en la primera opción.
La siguiente figura muestra el esquema de conexión del FPGA a un controlador externo para descargar en modo PS.

Para iniciar la configuración, el maestro externo debe generar una transición de baja a alta en la línea nCONFIG . Tan pronto como el FPGA esté listo para recibir datos, formará un alto nivel en la línea nSTATUS . Después de eso, el maestro puede comenzar a transmitir datos en la línea DATA [0] y los pulsos de reloj correspondientes en la línea DCLK . Los datos deben transmitirse al dispositivo de destino hasta que se establezca un nivel alto en la línea CONF_DONE (o los datos no finalizan), y el FPGA cambia al estado de inicialización. Cabe señalar que después de que CONF_DONE se establece en uno, se deben aplicar dos pulsos de reloj más para que comience la inicialización de FPGA.
Los datos se transmiten por el bit menos significativo ( LSB ) hacia adelante, es decir, si el archivo de configuración contiene la secuencia 02 1B EE 01 FA (tome el ejemplo como está en el Manual), la secuencia debe formarse en la línea de datos:
0100-0000 1101-1000 0111-0111 1000-0000 0101-1111
Por lo tanto, solo se utilizan cinco líneas: líneas DATA [0] y DCLK para la transmisión en serie, líneas nCONFIG , nSTATUS , CONF_DONE para el control.
En esencia, el modo PS no es más que SPI con manipulación adicional de banderas.
La velocidad de transferencia de datos debe ser inferior a la frecuencia máxima indicada en la documentación; para la serie Cyclone IV E utilizada en el proyecto, es de 66 MHz.
La frecuencia mínima de transmisión no existe, teóricamente es posible suspender la configuración por un tiempo indefinido. Esto brinda excelentes oportunidades para la depuración paso a paso con la participación de un osciloscopio, que ciertamente utilizaremos.
La siguiente figura muestra el diagrama de tiempos de la interfaz con los tiempos más significativos.

Sly Beast MPSSE
Considere la operación de FTDI en modo MPSSE. El modo MPSSE (Multi-Protocol Synchronous Serial Engine), en mi opinión, es un intento más o menos exitoso de crear un cierto diseñador de interfaz en serie, para darle al desarrollador la oportunidad de implementar protocolos de transferencia de datos generalizados, como SPI, I2C, JTAG, 1 cable y muchos otros basados en ellos.
Actualmente, el modo está disponible para microcircuitos: FT232H, FT2232D, FT2232H, FT4232H. En mi proyecto utilizo FT2232H, por lo que en mayor medida estamos hablando de eso. Para el modo MPSSE, se asignan 16 tramos, divididos en dos bytes: el L más bajo y el más alto H. Cada byte se puede leer o configurar. Las cuatro patas inferiores del byte L tienen funciones especiales: la transmisión de datos en serie puede ocurrir a través de ellas. Cada tramo se puede configurar como entrada o salida, se puede establecer un valor predeterminado para la salida. Para la transmisión secuencial, el orden de los bits ( MSB / LSB ), la longitud de la palabra transmitida, la frecuencia de los pulsos de reloj, la sincronización frontal - frontal (ascendente) o posterior (descendente), puede elegir transmitir solo pulsos de reloj sin datos, o seleccionar reloj trifásico (relevante para I2C) y mucho más.
Pasar sin problemas a la programación. Hay dos formas alternativas de interacción de software con chips FTDI: la primera, llamémosla clásica, en este caso, cuando se conecta a un puerto USB, el chip en el sistema se define como un puerto serie virtual (COM), el sistema operativo utiliza el controlador VCP (puerto COM virtual). Toda la programación adicional no difiere de la programación del puerto COM clásico: abierto - transmitido / contado - cerrado. Y esto es cierto para varios sistemas operativos, incluidos Linux y Mac OS. Sin embargo, con este enfoque, no será posible realizar todas las características del controlador FTDI: el chip funcionará como un adaptador USB-UART. El segundo método lo proporciona la biblioteca patentada FTD2XX, esta interfaz proporciona funciones especiales que no están disponibles en la API del puerto COM estándar, en particular, es posible configurar y utilizar modos de operación especiales, como MPSSE, 245 FIFO, Bit-bang. La biblioteca API FTD2XX está bien documentada por la Guía del Programador de Desarrollo de Aplicaciones de Software D2XX , ampliamente conocida por mucho tiempo en círculos estrechos. Y sí, FTD2XX también está disponible para varios sistemas operativos.
Los desarrolladores de FTDI se enfrentaron a la tarea de integrar el relativamente nuevo MPSSE en el modelo de interacción de software D2XX existente. Y tuvieron éxito, para trabajar en el modo MPSSE se usa el mismo conjunto de funciones que para otros modos "clásicos", se usa la misma biblioteca FTD2XX API.
En resumen, el algoritmo para operar en el modo MPSSE se puede describir de la siguiente manera:
- Encuentre el dispositivo en el sistema y ábralo.
- Inicialice el chip y póngalo en modo MPSSE.
- Establezca el modo de operación de MPSEE.
- Trabajo directo con datos: transmitir, recibir, administrar GPIO: implementamos el protocolo de intercambio de destino.
- Cierra el dispositivo.
Escribir un gestor de arranque
Pasemos a la parte práctica. En mis experimentos, usaré la versión Eclipse de Oxygen.3a Release (4.7.3a) como IDE, y mingw32-gcc (6.3.0) como compilador. Sistema operativo Win7.
Desde el sitio web de FTDI descargamos la última versión actual del controlador para nuestro sistema operativo. En el archivo encontramos el archivo de encabezado ftd2xx.h con una descripción de todas las funciones API. La API en sí se implementa como ftd2xx.dll, pero dejaremos la importación dinámica para más adelante y utilizaremos el enlace estático: necesitamos el archivo de biblioteca ftd2xx.lib. Para mi caso, ftd2xx.lib está en el directorio i386.
En Eclipse, cree un nuevo proyecto en C. Se puede confiar en la creación de un archivo MAKE con un IDE. En la configuración del vinculador, especifique la ruta y el nombre de la biblioteca ftd2xx (transfirí los archivos necesarios al directorio del proyecto en la carpeta ftdi). No me enfocaré en las características de configurar un proyecto para Eclipse, ya que sospecho que la mayoría de ellos usan otros entornos y compiladores para la programación de Win.
Punto uno Encuentra un dispositivo y ábrelo
La API FTD2XX le permite abrir el chip utilizando una u otra información conocida al respecto. Este puede ser su número de serie en el sistema: el primer chip FTDI conectado tomará el número 0, el siguiente 1 y así sucesivamente. El número en el sistema está determinado por el orden en que se conectan los microcircuitos, por decirlo suavemente, esto no siempre es conveniente. Para abrir el chip por número, se FT_Open
función FT_Open
. Puede abrir el chip por su número de serie ( FT_OPEN_BY_SERIAL_NUMBER
), descripción ( FT_OPEN_BY_DESCRIPTION
) o por ubicación ( FT_OPEN_BY_LOCATION
), para esto, se FT_OpenEx
función FT_OpenEx
. El número de serie y la descripción se almacenan en la memoria interna del chip y pueden registrarse allí durante la fabricación del dispositivo con FTDI instalado. La descripción, como regla, caracteriza el tipo de dispositivo o familia, y el número de serie debe ser único para cada producto. Por lo tanto, la forma más conveniente de identificar dispositivos compatibles con el programa que se está desarrollando es su descripción. Abriremos el chip FTDI de acuerdo con la descripción (descriptor). De hecho, si inicialmente conocíamos la línea de descripción del chip, entonces no necesitamos buscar el dispositivo en el sistema, sin embargo, como experimento, mostraremos todos los dispositivos conectados a la computadora con FTDI. Usando la función FT_CreateDeviceInfoList
, crearemos una lista detallada de chips conectados, y usando la función FT_GetDeviceInfoList
, FT_GetDeviceInfoList
consideraremos.
Lista de dispositivos conectados. Listado: ftStatus = FT_CreateDeviceInfoList(&numDevs); if (ftStatus == FT_OK) { printf("Number of devices is %d\n",numDevs); } if (numDevs == 0) return -1;
Bienvenido mi zoologico D:\workspace\ftdi-mpsse-ps\Debug>ftdi-mpsse-ps.exe Number of devices is 4 Dev 0: Flags = 0x0 Type = 0x5 ID = 0x4036001 LocId = 0x214 SerialNumber = AI043NNV Description = FT232R USB UART Dev 1: Flags = 0x2 Type = 0x6 ID = 0x4036010 LocId = 0x2121 SerialNumber = L731T70OA Description = LESO7 A Dev 2: Flags = 0x2 Type = 0x6 ID = 0x4036010 LocId = 0x2122 SerialNumber = L731T70OB Description = LESO7 B Dev 3: Flags = 0x2 Type = 0x8 ID = 0x4036014 LocId = 0x213 SerialNumber = FTYZ92L6 Description = LESO4.1_ER
Tres dispositivos con chips FTDI están conectados a mi PC: FT232RL (tipo 0x5), FT2232H (tipo 0x6) y FT232H (tepe 0x8). El chip FT2232H en el sistema se mostró como dos dispositivos independientes (Dev 1 y Dev 2). La interfaz FPGA PS está conectada a Dev 2, su descriptor es "LESO7 B". Ábrelo:
La mayoría de las funciones API devuelven el estado de su llamada de tipo FT_STATUS
, todos los valores posibles se describen como enum en el archivo de encabezado. Hay muchos de ellos, pero es suficiente saber que el valor FT_OK
es la ausencia de un error, todos los demás valores son códigos de error. Un buen estilo de programación es verificar el valor del estado después de cada llamada a la función API.
Si el dispositivo se abrió con éxito, en la variable ftHandle
aparece algún valor distinto de cero, un descriptor de archivo equivalente, que se utiliza cuando se trabaja con archivos. El identificador resultante establece una conexión con la interfaz de hardware y debe usarse al llamar a todas las funciones de la biblioteca que requieren acceso al chip.
Para confirmar en la práctica la operatividad del sistema para la etapa actual, debemos proceder inmediatamente al paso cinco de nuestro algoritmo.
Después de que termine de trabajar con el chip, debe cerrarlo. Para hacer esto, use la función FT_Close
:
FT_Close(ftHandle);
Punto 2. Inicialice el chip y encienda el MPSSE
La configuración es típica para la mayoría de los modos y está bien descrita en la documentación básica AN_135 FTDI MPSSE .
- Realizamos un reinicio (rezet) del chip. Función
FT_ResetDevice
. - En caso de que haya basura en el búfer de recepción, la limpiamos. Función
FT_Purge
. - Ajuste el tamaño de las memorias intermedias para leer y escribir. Función
FT_SetUSBParameters
. - Desactiva la paridad.
FT_SetChars
. - Establecemos tiempos de espera para leer y escribir. Por defecto, los tiempos de espera están deshabilitados, habilite el tiempo de espera de transmisión.
FT_SetTimeouts
. - Configuramos el tiempo de espera para enviar un paquete desde el chip al host. Por defecto, 16 ms, acelera a 1 ms.
FT_SetLatencyTimer
. - Active el control de flujo para sincronizar las solicitudes entrantes.
FT_SetFlowControl
. - Todo está listo para activar el modo MPSSE. Restablezca el controlador MPSSE. Usamos la función
FT_SetBitMode
, establecemos el modo en 0 (modo = 0, máscara = 0). - Active el modo MPSSE. Función
FT_SetBitMode
- modo = 2, máscara = 0.
MPSSE_open
y configuramos el chip en la función MPSSE_open
, como parámetro pasamos una línea con el controlador del dispositivo que se abrirá:
Listado MPSSE_open static FT_STATUS MPSSE_open (char *description) { FT_STATUS ftStatus; ftStatus = FT_OpenEx(description, FT_OPEN_BY_DESCRIPTION, &ftHandle); if (ftStatus != FT_OK) { printf ("open failure\r\n"); return FT_DEVICE_NOT_OPENED; } printf ("open OK, %d\r\n", ftHandle); printf("\nConfiguring port for MPSSE use...\n"); ftStatus |= FT_ResetDevice(ftHandle);
Elemento 3. Configure el modo de operación MPSEE
En realidad, en esta etapa, el procesador MPSSE está activado y listo para recibir comandos. Los comandos son secuencias de bytes, el primer byte es "op-code", seguido de los parámetros del comando. El comando puede no tener parámetros y constar de un "código operativo". Los comandos se transmiten usando la función FT_Write, se puede obtener una respuesta del procesador MPSSE usando la función FT_Read
.
Después de enviar cada comando, es útil leer la respuesta del procesador, ya que en caso de un comando incorrecto, la respuesta puede contener un mensaje de error: el carácter 0xFA. El mecanismo de "comando incorrecto: respuesta 0xFA" se puede utilizar para sincronizar el programa de aplicación con el procesador MPSSE. Si todo está bien, entonces el chip devolverá el carácter 0xFA en un comando deliberadamente erróneo. Los códigos operativos se describen en el Procesador de comandos para el modo de emulación de bus de host MPSSE y MCU .
La configuración de MPSSE se reduce a establecer la velocidad de datos, la dirección y los estados iniciales de las líneas de E / S.
Considere configurar la velocidad de datos del procesador MPSSE. Las configuraciones para chips con soporte solo para modo de velocidad completa (FT2232 D ) y chips con alta velocidad (FT2232 H , FT232H, FT4232H) son algo diferentes. El FT2232D heredado usa un reloj de 12MHz, mientras que los modernos usan 60MHz. De ahí la fórmula para calcular la velocidad de transferencia de datos:
donde f core es la frecuencia central FTDI, Divisor es un divisor de dos bytes que, de hecho, establece la frecuencia del reloj de datos.
Como resultado, si el divisor es cero, entonces la velocidad de datos máxima será de 30 Mbps, y la velocidad de datos mínima será de 458 bits / s con el divisor 65535.
Confiaremos el cálculo del divisor al preprocesador. La macro devuelve el divisor:
#define FCORE 60000000ul #define MPSSE_DATA_SPEED_DIV(data_speed) ((FCORE/(2*data_speed)) -1)
Y estas dos macros devuelven los bytes alto y bajo del divisor respectivamente:
#define MPSSE_DATA_SPEED_DIV_H(data_speed) ((MPSSE_DATA_SPEED_DIV(data_speed)) >> 8) #define MPSSE_DATA_SPEED_DIV_L(data_speed) \ (MPSSE_DATA_SPEED_DIV(data_speed) - (MPSSE_DATA_SPEED_DIV_H(data_speed)<< 8))
Además, debe tenerse en cuenta que en los chips modernos para compatibilidad con el antiguo FT2232D hay un divisor adicional de 5, que convierte 60 MHz en 12 MHz. Este divisor está activado por defecto, en nuestro caso debería estar apagado.
Encontramos el código de operación correspondiente (0x8A) y el comando del casco para el procesador:
Listado de envío de equipo BYTE byOutputBuffer[8], byInputBuffer[8]; DWORD dwNumBytesToRead, dwNumBytesSent = 0, dwNumBytesRead = 0; byOutputBuffer[0] = 0x8A; ftStatus = FT_Write(ftHandle, byOutputBuffer, 1, &dwNumBytesSent); Sleep(2);
Como experimento, en lugar del comando real 0x8A, enviaremos el valor 0xFE, que no corresponde a ningún código operativo, la salida de la consola:
dwNumBytesToRead = 2: FAh FEh
El procesador devolvió dos bytes, el byte de comando incorrecto es 0xFA y el valor de este comando incorrecto. Por lo tanto, al enviar varios comandos a la vez, no solo podemos rastrear el hecho del error en sí, sino también entender en qué equipo se produjo este error.
Para no tratar con "números mágicos" en el futuro, formatearemos todos los códigos de operación en forma de constantes y los colocaremos en un archivo de encabezado separado.
Para configurar completamente el modo, debe especificar la dirección de las líneas de E / S y su valor predeterminado. Pasemos al diagrama de conexión. Para no saturar un artículo ya hinchado, he dibujado un fragmento interesante del esquema:

Las líneas DCLK , DATA [0] , nCONFIG deben configurarse como salidas, las líneas nSTATUS , CONF_DONE como entradas. Usando el diagrama, determinamos qué estados iniciales deben tener las líneas. Para mayor claridad, el pinout del circuito se resume en la tabla:
Pin FPGA | Nombre pin | Pin | MPSSE | Dirección | por defecto |
---|
DCLK | BDBUS0 | 38 | TCK / SK | Fuera | 0 0 |
DATOS [0] | BDBUS1 | 39 | TDI / DO | Fuera | 1 |
nCONFIG | BDBUS2 | 40 | TDO / DI | Fuera | 1 |
n ESTADO | BDBUS3 | 41 | TMS / CS | En | 1 |
CONF_DONE | BDBUS4 | 43 | GPIOL0 | En | 1 |
Todas las líneas utilizadas se encuentran en el byte bajo del puerto MPSSE. Para establecer el valor, use el código de operación 0x80. Este comando asume dos argumentos: el primer byte que sigue al código de operación es el valor bit por bit, y el segundo es la dirección (uno es el puerto de salida, cero es el puerto de entrada).
Como parte de la lucha contra el "número mágico", todos los números de línea en serie y sus valores predeterminados se formatearán como constantes:
Definir puertos #define PORT_DIRECTION (0x07) #define DCLK (0) #define DATA0 (1) #define N_CONFIG (2) #define N_STATUS (3) #define CONF_DONE (4)
Solo queda asegurarse de que el bucle TDI - TDO esté deshabilitado (se puede activar para probar) y ponerlo en una función separada:
Listado de la función MPSSE_setup static FT_STATUS MPSSE_setup () { DWORD dwNumBytesToSend, dwNumBytesSent, dwNumBytesToRead, dwNumBytesRead; BYTE byOutputBuffer[8], byInputBuffer[8]; FT_STATUS ftStatus;
Punto 4. Implementamos el protocolo de carga
Todo parece listo para experimentos prácticos. Primero, verifique que la inicialización se realice correctamente, en el cuerpo principal del programa, llame a MPSSE_open()
y MPSSE_setup()
, y antes de cerrar el dispositivo ( FT_Close
), colocamos un getchar()
vacío getchar()
. Ejecute el programa y use el osciloscopio para asegurarse de que todas las líneas PS estén configuradas en los niveles predeterminados. Cambiando el valor de estos niveles en la inicialización (no ocurrirá nada malo con el FPGA), nos aseguramos de que el procesador MPSSE dé el resultado deseado como válido: todo funciona adecuadamente y puede proceder a transferir datos.
El envío y la recepción secuenciales de datos se realizan en modo comando usando el mismo código de operación. El primer byte del comando es el código de operación, que determina el tipo de operación, seguido de la longitud de la secuencia transmitida o recibida y, si es una transmisión, los datos reales. El procesador MPSSE puede enviar y recibir datos, también lo hace al mismo tiempo. La transmisión puede ser el bit bit forward menos significativo (LSB) o el más significativo (MSB). La transmisión de datos puede ocurrir tanto en los bordes iniciales como finales de los pulsos de reloj. Cada combinación de opciones tiene su propio código de operación, cada bit de código de operación describe el modo de operación:
Poco | Función |
---|
0 0 | Sincronización de escritura frontal: 0 - positivo, 1 - negativo |
1 | 1 - trabajar con bytes, 0 - trabajar con bits |
2 | Borde frontal para lectura: 0 - positivo, 1 - negativo |
3 | Modo de transmisión: 1 - LSB, 0 - MSB primero |
4 4 | Transmisión de datos TDI |
5 5 | Lectura de datos de una línea TDO |
6 6 | Transmisión de datos TMS |
7 7 | Debe ser 0, de lo contrario, este es otro grupo de comandos |
Al configurar FPGA de acuerdo con el esquema PS, los datos se transmiten en el borde de ataque en modo LSB. , , op-code 0001_1000b 0x18 . ( , ), . : . , , 0, 65536, 65535. , . MPSSE_send
.
MPSSE_send static BYTE byBuffer[65536 + 3]; static FT_STATUS MPSSE_send(BYTE * buff, DWORD dwBytesToWrite) { DWORD dwNumBytesToSend = 0, dwNumBytesSent, bytes; FT_STATUS ftStatus;
— 65 , - , op-code . byBuffer
, buff
, , op-code . , , .
, "" , 25 , , , 1 ( , #define DATA_SPEED 1000000ul
). :
BYTE byOutputBuffer[] = {0x02, 0x1B, 0xEE, 0x01, 0xFA}; MPSSE_send(byOutputBuffer, sizeof(byOutputBuffer));
( ):

— DATA[0] , — DCLK . . , , .
, SPI ( ). , PS, . nCONFIG , nSTATUS , CONF_DONE . — , , — , .
MPSSE_get_lbyte
, , .
MPSSE_get_lbyte static FT_STATUS MPSSE_get_lbyte(BYTE *lbyte) { DWORD dwNumBytesToSend, dwNumBytesSent, dwNumBytesToRead, dwNumBytesRead; BYTE byOutputBuffer[8]; FT_STATUS ftStatus; dwNumBytesToSend = 0; byOutputBuffer[dwNumBytesToSend++] = MPSSE_CMD_GET_DATA_BITS_LOWBYTE; ftStatus = FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent); Sleep(2);
, op-code , . , - , , . , . MPSSE_set_lbyte
:
MPSSE_set_lbyte static FT_STATUS MPSSE_set_lbyte(BYTE lb, BYTE mask) { DWORD dwNumBytesToSend, dwNumBytesSent; BYTE byOutputBuffer[8], lbyte; FT_STATUS ftStatus; ftStatus = MPSSE_get_lbyte(&lbyte); if ( ftStatus != FT_OK) return ftStatus;
, . : FTDI; MPSSE; rbf- , nCONFIG , N_STATUS ; rbf- ; , , CONF_DONE . , MPSSE FTDI . , nCONFIG "" , , , .
main int main(int argc, char *argv[]) { FT_STATUS ftStatus; BYTE lowByte; DWORD numDevs;
:
pen "LESO7 B" OK nConfig -> 0 nConfig -> 1 ** Load complete Configuration complete
rbf- . . 30 / .
, - JTAG.
Materiales relacionados
- FTDI-MPSSE-Altera PS . .
- . . .
- Software Application Development D2XX Programmer's Guide . FTDI. API D2XX.
- FTDI MPSSE Basics. Application Note AN_135 . . FTDI MPSSE. .
- Procesador de comandos para los modos de emulación de bus host MPSSE y MCU. Nota de aplicación AN_108 . Referencia para el código de operación. De ninguna manera sin eso.
- Controladores D2XX . Conductor FTDI.