
Na vida de cada gaveta, chega um momento em que você deseja gravar seu próprio carregador do arquivo de configuração no FPGA. Eu tive que participar do desenvolvimento de um estande de treinamento para o departamento de uma universidade técnica. O estande foi projetado para estudar o processamento de sinal digital, embora isso não seja de particular importância na estrutura deste artigo. E o significado é que o FPGA (Altera Cyclone IV) está no centro do estande, no qual os alunos colecionam todos os tipos de esquemas de DSP, conforme concebido pelo autor do estande. O suporte está conectado ao computador via USB. Você precisa baixar o FPGA do computador via USB.
Foi tomada a decisão de conectar-se a um PC usando o FTDI em sua encarnação de canal duplo - FT2232H. Um canal será usado para a configuração FPGA, o outro pode ser usado para a troca FIFO de alta velocidade.
O FTDI possui uma placa de depuração MORPH-IC-II , na qual o FPGA do Cyclone II é piscado via USB. Conceitos de domínio público. O código fonte do carregador de inicialização está parcialmente aberto: o próprio carregador de inicialização está disponível, no entanto, toda a lógica de trabalhar com o FTDI é movida para uma biblioteca privada e não pode ser modificada. Na verdade, originalmente planejei usar esse gerenciador de inicialização no meu projeto ou, em casos extremos, criar meu shell com base na dll deles. O firmware é carregado no FPGA no modo serial passivo (serial passivo - PS), o FTDI opera no modo MPSSE. Na placa de ensaio, o desempenho da solução MORPH-IC-II foi totalmente confirmado, mas o problema, como costuma acontecer, não veio de onde. Verificou-se que, durante a operação da dll MORPH-IC-II, todos os dispositivos FTDI conectados são bloqueados e, como parte do complexo de treinamento, existem mais dois dispositivos com conversores semelhantes: um gerador e um analisador de sinais. O trabalho simultâneo com eles não é possível. Maldito estranho e irritante.
Um caso semelhante foi implementado pelos caras do rover Mars: programador USB JTAG MBFTDI . O FTDI também é usado no modo MPSSE, mas, diferentemente do MORPH-IC-II, as operações do FPGA são executadas no modo JTAG. As fontes estão disponíveis gratuitamente, mas não encontrei uma indicação clara de seu status (licença). Portanto, para usá-los em um projeto comercial, minha mão não se levantou.
Corrigirei esse erro, tudo o que será apresentado na estrutura deste artigo será publicado em um repositório aberto sob a licença BSD.
Baixe o arquivo de configuração para o chip FPGA
Primeiro de tudo, você deve lidar com o modo de inicialização do FPGA. Para aqueles que estão começando a se familiarizar com o assunto, farei uma pequena excursão. Embora os FPGAs da Altera (Intel) da família Cyclone IV E estejam instalados na minha placa, os métodos de carregamento são semelhantes para todo o grupo Cyclone FPGA, e há uma suspeita de que, de uma forma ou de outra, sejam adequados para muitas outras famílias.
Esse tipo de FPGA usa SRAM volátil para armazenar dados de configuração. Esses dados de configuração determinam a funcionalidade do dispositivo resultante. No jargão profissional, esses dados costumam ser chamados de "firmware". Assim, o firmware é armazenado em uma RAM especial e cada vez que o dispositivo é ligado, ele deve ser carregado no chip FPGA. Existem várias maneiras (esquemas de configuração) pelas quais o firmware pode ser carregado na SRAM (a lista é relevante para o Cyclone IV E):
- Serial ativo (AS).
- Paralelo ativo (AP)
- Série passiva (PS)
- Paralelo passivo rápido (FPP).
- JTAG.
A escolha de um modo de inicialização específico é realizada usando os terminais externos do FPGA (grupo MSEL). O modo JTAG está sempre disponível. O modo ativo implica que, quando a energia é aplicada, o FPGA lê independentemente os dados da memória externa (serial ou paralela). No modo passivo, o FPGA aguarda um meio externo transferir proativamente os dados de configuração para ele. Esses esquemas se encaixam bem no conceito de mestre (mestre) - escravo (escravo). Nos modos ativos, o FPGA atua como mestre e, nos modos passivos, como escravo.
Nesse problema, não é o FPGA, mas o usuário deve decidir quando o firmware deve ser atualizado, portanto o modo de inicialização deve ser passivo. E para salvar as pernas do chip, escolhemos uma interface serial. O modo serial passivo (PS) e o JTAG são adequados aqui. A lógica do JTAG é um pouco mais complicada, então vamos nos concentrar na primeira opção.
A figura abaixo mostra o esquema de conexão do FPGA a um controlador externo para download no modo PS.

Para iniciar a configuração, o mestre externo deve gerar uma transição de baixa para alta na linha nCONFIG . Assim que o FPGA estiver pronto para receber dados, ele formará um alto nível na linha nSTATUS . Depois disso, o mestre pode começar a transmitir dados na linha DATA [0] e o relógio correspondente pulsa na linha DCLK . Os dados devem ser transmitidos ao dispositivo de destino até que um nível alto seja estabelecido na linha CONF_DONE (ou os dados não terminam) e o FPGA alterna para o estado de inicialização. Deve-se observar que, depois que CONF_DONE é definido como um, mais dois pulsos de clock devem ser aplicados para que a inicialização do FPGA comece.
Os dados são transmitidos pelo encaminhamento de bit menos significativo ( LSB ), ou seja, se o arquivo de configuração contiver a sequência 02 1B EE 01 FA (como o exemplo está no Manual), a sequência deve ser formada na linha de dados:
0100-0000 1101-1000 0111-0111 1000-0000 0101-1111
Assim, apenas cinco linhas são usadas: linhas DATA [0] e DCLK para transmissão serial, linhas nCONFIG , nSTATUS , CONF_DONE para controle.
Na sua essência, o modo PS nada mais é do que SPI com manipulação adicional de sinalizadores.
A taxa de transferência de dados deve ser menor que a frequência máxima indicada na documentação; para a série Cyclone IV E usada no projeto, é de 66 MHz.
A frequência mínima de transmissão não existe, teoricamente é possível suspender a configuração por tempo indeterminado. Isso oferece excelentes oportunidades para a depuração passo a passo com a participação de um osciloscópio, que certamente usaremos.
A figura abaixo mostra o diagrama de tempo da interface com os tempos mais significativos.

Sly Beast MPSSE
Considere a operação do FTDI no modo MPSSE. O modo MPSSE (Multi-Protocol Synchronous Serial Engine), na minha opinião, é uma tentativa mais ou menos bem-sucedida de criar um certo designer de interface serial, para dar ao desenvolvedor a oportunidade de implementar protocolos de transferência de dados generalizados, como SPI, I2C, JTAG, 1-wire e muitos outros baseados neles.
Atualmente, o modo está disponível para microcircuitos: FT232H, FT2232D, FT2232H, FT4232H. No meu projeto eu uso o FT2232H, então estamos falando mais sobre isso. Para o modo MPSSE, 16 pernas são alocadas, divididas em dois bytes: o L mais baixo e o H. mais alto. Cada byte pode ser lido ou definido. As quatro pernas inferiores do byte L têm funções especiais - a transmissão de dados seriais pode ocorrer através deles. Cada perna pode ser configurada como uma entrada ou saída, um valor padrão pode ser definido para a saída. Para transmissão sequencial, a ordem dos bits ( MSB / LSB ), o comprimento da palavra transmitida, a frequência dos pulsos de relógio, a sincronização frente - frente (Rising) ou traseira (Falling), você pode optar por transmitir apenas pulsos de relógio sem dados ou selecionar o relógio trifásico (relevante para I2C) e muito mais.
Passar sem problemas para a programação. Existem duas maneiras alternativas de interação do software com os chips FTDI: o primeiro, vamos chamar de clássico, neste caso, quando conectado a uma porta USB, o chip no sistema é definido como uma porta serial virtual (COM), o sistema operacional usa o driver VCP (porta virtual COM). Toda a programação adicional não difere da programação da porta COM clássica: aberta - transmitida / contada - fechada. E isso é verdade para vários sistemas operacionais, incluindo Linux e Mac OS. No entanto, com essa abordagem, não será possível realizar todos os recursos do controlador FTDI - o chip funcionará como um adaptador USB-UART. O segundo método é fornecido pela biblioteca proprietária do FTD2XX; essa interface fornece funções especiais que não estão disponíveis na API da porta COM padrão; em particular, é possível configurar e usar modos operacionais especiais, como MPSSE, 245 FIFO, Bit-bang. A biblioteca da API do FTD2XX está bem documentada pelo Guia do Programador de Desenvolvimento de Aplicativos de Software D2XX , amplamente conhecido por muito tempo em círculos estreitos. E sim, o FTD2XX também está disponível para vários sistemas operacionais.
Os desenvolvedores de FTDI foram confrontados com a tarefa de integrar o relativamente novo MPSSE ao modelo de interação de software D2XX existente. E eles conseguiram, para trabalhar no modo MPSSE, o mesmo conjunto de funções é usado como para outros modos "clássicos", a mesma biblioteca FTD2XX API é usada.
Em resumo, o algoritmo para operar no modo MPSSE pode ser descrito da seguinte maneira:
- Encontre o dispositivo no sistema e abra-o.
- Inicialize o chip e coloque-o no modo MPSSE.
- Defina o modo de operação do MPSEE.
- Trabalho direto com dados: transmita, receba, gerencie GPIO - implementamos o protocolo de troca de destino.
- Feche o dispositivo
Escrevendo um gerenciador de inicialização
Vamos direto à parte prática. Nas minhas experiências, usarei a versão Eclipse do Oxygen.3a Release (4.7.3a) como IDE e o mingw32-gcc (6.3.0) como compilador. Sistema operacional Win7.
No site da FTDI , baixamos a versão atual mais recente do driver para o nosso sistema operacional. No arquivo, encontramos o arquivo de cabeçalho ftd2xx.h com uma descrição de todas as funções da API. A API em si é implementada como ftd2xx.dll, mas deixaremos a importação dinâmica para mais tarde e usaremos o link estático: precisamos do arquivo de biblioteca ftd2xx.lib. Para o meu caso, o ftd2xx.lib está no diretório i386.
No Eclipse, crie um novo projeto C. A criação de um makefile pode ser confiável com um IDE. Nas configurações do vinculador, especifique o caminho e o nome da biblioteca ftd2xx (transferi os arquivos necessários para o diretório do projeto na pasta ftdi). Não vou me concentrar nos recursos da configuração de um projeto para o Eclipse, pois suspeito que a maioria deles use outros ambientes e compiladores para a programação do Win.
Ponto um. Encontre um dispositivo e abra-o
A API do FTD2XX permite abrir o chip usando uma ou outra informação conhecida sobre ele. Este pode ser o número de série no sistema: o primeiro chip FTDI conectado receberá o número 0, o próximo 1 e assim por diante. O número no sistema é determinado pela ordem em que os microcircuitos são conectados, para dizer o mínimo, isso nem sempre é conveniente. Para abrir o chip por número, é FT_Open
função FT_Open
. Você pode abrir o chip por seu número de série ( FT_OPEN_BY_SERIAL_NUMBER
), descrição ( FT_OPEN_BY_DESCRIPTION
) ou por local ( FT_OPEN_BY_LOCATION
); para isso, a função FT_OpenEx
é FT_OpenEx
. O número de série e a descrição são armazenados na memória interna do chip e podem ser gravados durante o fabrico do dispositivo com o FTDI instalado. A descrição, como regra, caracteriza o tipo de dispositivo ou família e o número de série deve ser exclusivo para cada produto. Portanto, a maneira mais conveniente de identificar dispositivos suportados pelo programa em desenvolvimento é sua descrição. Abriremos o chip FTDI de acordo com a descrição (descritor). De fato, se conhecemos inicialmente a linha de descritores de chips, não precisamos procurar o dispositivo no sistema; no entanto, como um experimento, exibiremos todos os dispositivos conectados ao computador com FTDI. Usando a função FT_CreateDeviceInfoList
, criaremos uma lista detalhada de chips conectados e, usando a função FT_GetDeviceInfoList
, a consideraremos.
Lista de dispositivos conectados. Listagem: ftStatus = FT_CreateDeviceInfoList(&numDevs); if (ftStatus == FT_OK) { printf("Number of devices is %d\n",numDevs); } if (numDevs == 0) return -1;
Welcome my zoo 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
Três dispositivos com chips FTDI estão conectados ao meu PC: FT232RL (tipo 0x5), FT2232H (tipo 0x6) e FT232H (tepe 0x8). O chip FT2232H no sistema foi exibido como dois dispositivos independentes (Dev 1 e Dev 2). A interface do FPGA PS está conectada ao Dev 2, e seu descritor é "LESO7 B". Abra:
A maioria das funções da API retorna o status de sua chamada do tipo FT_STATUS
, todos os valores possíveis são descritos como enumeração no arquivo de cabeçalho. Existem muitos deles, mas é suficiente saber que o valor FT_OK
é a ausência de erro, todos os outros valores são códigos de erro. Um bom estilo de programação é verificar o valor do status após cada chamada para a função API.
Se o dispositivo foi aberto com êxito, na variável ftHandle
aparece algum valor diferente de zero, algum descritor de arquivo equivalente, usado ao trabalhar com arquivos. O identificador resultante estabelece uma conexão com a interface de hardware e deve ser usado ao chamar todas as funções da biblioteca que requerem acesso ao chip.
Para confirmar na prática a operacionalidade do sistema para o estágio atual, devemos prosseguir imediatamente para a etapa cinco do nosso algoritmo.
Depois de terminar de trabalhar com o chip, você precisa fechá-lo. Para fazer isso, use a função FT_Close
:
FT_Close(ftHandle);
Ponto 2. Inicialize o chip e ligue o MPSSE
A configuração é típica para a maioria dos modos e está bem descrita na documentação AN_135 FTDI MPSSE Basics .
- Realizamos uma redefinição (rezet) do chip. Função
FT_ResetDevice
. - Caso haja algum lixo no buffer de recebimento, nós o limpamos. Função
FT_Purge
. - Ajuste o tamanho dos buffers para leitura e gravação. Função
FT_SetUSBParameters
. - Desative a paridade.
FT_SetChars
. - Estabelecemos tempos limite para leitura e escrita. Por padrão, os tempos limite estão desativados, ative o tempo limite da transmissão.
FT_SetTimeouts
. - Configuramos o tempo de espera para enviar um pacote do chip para o host. Por padrão, 16 ms, acelere para 1 ms.
FT_SetLatencyTimer
. - Ative o controle de fluxo para sincronizar solicitações recebidas.
FT_SetFlowControl
. - Tudo está pronto para ativar o modo MPSSE. Redefina o controlador MPSSE. Usamos a função
FT_SetBitMode
, defina o modo como 0 (mode = 0, mask = 0). - Ligue o modo MPSSE. Função
FT_SetBitMode
- mode = 2, mask = 0.
MPSSE_open
e configuramos o chip na função MPSSE_open
, como parâmetro, passamos uma linha com a alça do dispositivo a ser aberto:
Listagem 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);
Item 3. Configure o modo de operação MPSEE
Na verdade, nesta fase, o processador MPSSE está ativado e pronto para receber comandos. Comandos são sequências de bytes, cujo primeiro byte é "código operacional", seguido pelos parâmetros do comando. O comando pode não ter parâmetros e consistir em um "código operacional". Os comandos são transmitidos usando a função FT_Write
, uma resposta do processador MPSSE pode ser obtida usando a função FT_Read
.
Após o envio de cada comando, é útil ler a resposta do processador, pois, no caso de um comando incorreto, a resposta pode conter uma mensagem de erro - o caractere 0xFA. O mecanismo "comando inválido - resposta 0xFA" pode ser usado para sincronizar o programa de aplicativo com o processador MPSSE. Se tudo estiver correto, o chip retornará o caractere 0xFA em um comando deliberadamente incorreto. Os códigos operacionais são descritos no Processador de comandos para o modo de emulação de barramento de host MPSSE e MCU .
A configuração do MPSSE se resume a definir a taxa de dados, a direção e os estados iniciais das linhas de E / S.
Considere definir a taxa de dados do processador MPSSE. As configurações de chips com suporte apenas para o modo de velocidade total (FT2232 D ) e chips com alta velocidade (FT2232 H , FT232H, FT4232H) são um pouco diferentes. O FT2232D herdado usa um relógio de 12MHz, enquanto os modernos usam 60MHz. Daí a fórmula para calcular a taxa de transferência de dados:
onde f core é a frequência principal do FTDI, o Divisor é um divisor de dois bytes que, de fato, define a frequência do relógio de dados.
Como resultado, se o divisor for igual a zero, a taxa máxima de transferência de dados será de 30 Mbps e a taxa mínima de transferência de dados será de 65535 a 458 bits / s.
Confiaremos o cálculo do divisor ao pré-processador. A macro retorna o divisor:
#define FCORE 60000000ul #define MPSSE_DATA_SPEED_DIV(data_speed) ((FCORE/(2*data_speed)) -1)
E essas duas macros retornam os bytes alto e baixo do 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))
Além disso, deve-se notar que em chips modernos para compatibilidade com o antigo FT2232D, há um divisor adicional de 5, que transforma 60 MHz em 12 MHz. Esse divisor é ativado por padrão; no nosso caso, deve ser desativado.
Encontramos o código operacional correspondente (0x8A) e o comando do capacete para o processador:
Listagem de envio da equipe BYTE byOutputBuffer[8], byInputBuffer[8]; DWORD dwNumBytesToRead, dwNumBytesSent = 0, dwNumBytesRead = 0; byOutputBuffer[0] = 0x8A; ftStatus = FT_Write(ftHandle, byOutputBuffer, 1, &dwNumBytesSent); Sleep(2);
Como um experimento, em vez do comando real 0x8A, enviaremos o valor 0xFE, que não corresponde a nenhum código operacional, a saída do console:
dwNumBytesToRead = 2: FAh FEh
O processador retornou dois bytes, o byte de comando incorreto é 0xFA e o valor desse comando incorreto. Assim, enviando vários comandos de uma só vez, podemos não apenas rastrear o fato do erro em si, mas também entender em qual equipe esse erro ocorreu.
Para não lidar com "números mágicos" no futuro, formataremos todos os códigos operacionais na forma de constantes e os colocaremos em um arquivo de cabeçalho separado.
Para configurar completamente o modo, você deve especificar a direção das linhas de E / S e seu valor padrão. Vamos passar para o diagrama de conexão. Para não desordenar um artigo já inchado, desenhei um fragmento interessante do esquema:

As linhas DCLK , DATA [0] , nCONFIG devem ser configuradas como saídas, as linhas nSTATUS , CONF_DONE como entradas. Usando o diagrama, determinamos quais estados iniciais as linhas devem ter. Para maior clareza, a pinagem do circuito está resumida na tabela:
Pino FPGA | Nome do PIN | Pin | MPSSE | Direção | padrão |
---|
DCLK | BDBUS0 | 38. | TCK / SK | Fora | 0 0 |
DADOS [0] | BDBUS1 | 39. | TDI / DO | Fora | 1 |
nCONFIG | BDBUS2 | 40. | TDO / DI | Fora | 1 |
nSTATUS | BDBUS3 | 41. | TMS / CS | Em | 1 |
CONF_DONE | BDBUS4 | 43 | GPIOL0 | Em | 1 |
Todas as linhas usadas estão localizadas no byte baixo da porta MPSSE. Para definir o valor, use o código op 0x80. Este comando assume dois argumentos: o primeiro byte após o código operacional é o valor bit a bit e o segundo é a direção (uma é a porta de saída, zero é a porta de entrada).
Como parte da luta contra o "número mágico", todos os números de linha de série e seus valores padrão serão formatados como constantes:
Definir portas #define PORT_DIRECTION (0x07) #define DCLK (0) #define DATA0 (1) #define N_CONFIG (2) #define N_STATUS (3) #define CONF_DONE (4)
Resta apenas garantir que o loop TDI - TDO esteja desativado (pode ser ativado para teste) e colocá-lo em uma função separada:
Listando a função MPSSE_setup static FT_STATUS MPSSE_setup () { DWORD dwNumBytesToSend, dwNumBytesSent, dwNumBytesToRead, dwNumBytesRead; BYTE byOutputBuffer[8], byInputBuffer[8]; FT_STATUS ftStatus;
Ponto 4. Implementamos o protocolo de carregamento
Tudo parece pronto para experimentos práticos. Primeiro, verifique se a inicialização foi realizada corretamente, no corpo principal do programa, chame MPSSE_open()
e MPSSE_setup()
e, antes de fechar o dispositivo ( FT_Close
), colocamos um getchar()
vazio getchar()
. Execute o programa e use o osciloscópio para garantir que todas as linhas PS estejam definidas nos níveis padrão. Alterando o valor desses níveis na inicialização (nada de ruim acontecerá com o FPGA), garantimos que o processador MPSSE dê o resultado desejado como válido - tudo funciona adequadamente e você pode continuar transferindo dados.
O envio e o recebimento sequenciais de dados são realizados no modo de comando usando o mesmo código operacional. O primeiro byte do comando é op-code, que determina o tipo de operação, seguido pelo comprimento da sequência transmitida ou recebida e, se for uma transmissão, os dados reais. O processador MPSSE pode enviar e receber dados e também fazê-lo ao mesmo tempo. A transmissão pode ser o menos significativo bit forward (LSB) ou o mais significativo (MSB). A transmissão de dados pode ocorrer nas bordas anterior ou posterior dos pulsos do relógio. Cada combinação de opções possui seu próprio código operacional, cada bit do código operacional descreve o modo de operação:
Bit | Função |
---|
0 0 | Sincronização de gravação frontal: 0 - positivo, 1 - negativo |
1 | 1 - trabalhar com bytes, 0 - trabalhar com bits |
2 | Borda frontal para leitura: 0 - positivo, 1 - negativo |
3 | Modo de transmissão: 1 - LSB, 0 - MSB primeiro |
4 | Transmissão de dados TDI |
5 | Lendo dados de uma linha TDO |
6 | Transmissão de dados TMS |
7 | Deve ser 0, caso contrário, este é outro grupo de comandos |
Ao configurar FPGAs de acordo com o esquema PS, os dados são transmitidos na borda principal no 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;
Exemplo de como iniciar um programa:
pen "LESO7 B" OK nConfig -> 0 nConfig -> 1 ** Load complete Configuration complete
rbf- . . 30 / .
, - JTAG.
- FTDI-MPSSE-Altera PS . .
- . . .
- Software Application Development D2XX Programmer's Guide . FTDI. API D2XX.
- FTDI MPSSE Basics. Application Note AN_135 . . FTDI MPSSE. .
- Processador de comando para os modos de emulação de barramento de host MPSSE e MCU. Nota de aplicação AN_108 . Referência para código operacional. De jeito nenhum sem ele.
- Drivers D2XX . Driver FTDI.