📄 hal_m5i20.c
字号:
rtapi_print_msg(RTAPI_MSG_ERR, "M5I20: ERROR: hal_create_thread() failed\n"); hal_exit(driver.componentId); return(-1); } else { rtapi_print_msg(RTAPI_MSG_INFO, "M5I20: created %d uS thread\n", period / 1000); } } return(0);}voidrtapi_app_exit(void){ int i; Device *pDevice; hal_exit(driver.componentId); for(i = 0; i < MAX_DEVICES; i++){ if((pDevice = driver.deviceTable[i]) != NULL){ // Unmap card. iounmap((void *)(pDevice->pCard16)); iounmap((void *)(pDevice->pCard32)); iounmap((void *)(pDevice->pBridgeIc)); // TODO: Free device object when HAL supports free.// hal_free(pDevice); } }}/****************************************************************************** * DEVICE OBJECT FUNCTION DEFINITIONS ******************************************************************************//* * LOCAL FUNCTIONS */static intDevice_Init(Device *this, M5i20HostMotRegMap *pCard16, M5i20HostMotRegMap *pCard32, Plx9030LocalRegMap *pBridgeIc){ int i; this->pCard16 = pCard16; this->pCard32 = pCard32; this->pBridgeIc = pBridgeIc; // Download FPGA configuration. if(loadFpga && ((i = Device_LoadFpga(this)) != 0)){ return(i); } // Initialize hardware. pCard16->mode = 0; pCard16->ledView = 0; pCard16->pwmRate = dacRate * 65536 / 1000 * 1024 / 33000; pCard16->wdTimeout = 16000; pCard16->control = M5I20_CONTROL_RESET_WDT | M5I20_CONTROL_CLEAR_IRQ | M5I20_CONTROL_CLEAR_PWMS | M5I20_CONTROL_CLEAR_ENCODERS; // Initialize PWM channels. for(i = 0; i < M5I20_NUM_PWM_CHANNELS; i++){ this->lastDacInterlaced[i] = 1; pCard16->pwmControl[i] = M5I20_PWM_CTL_SIGNED | M5I20_PWM_CTL_INTERLACED; } // Initialize primary encoders. for(i = 0; i < M5I20_NUM_PRIMARY_ENCODERS; i++){ pCard16->encoderControl[i] = M5I20_ENC_CTL_COUNT_QUADRATURE | M5I20_ENC_CTL_INDEX_ACTIVE_HI | M5I20_ENC_CTL_QUAD_FILTER_4MHZ | M5I20_ENC_CTL_LATCH_ON_READ | M5I20_ENC_CTL_LOCAL_CLEAR; } // Initialize secondary encoders. for(i = M5I20_MAX_PRIMARY_ENCODERS; i < M5I20_MAX_PRIMARY_ENCODERS + M5I20_NUM_SECONDARY_ENCODERS; i++){ pCard16->encoderControl[i] = M5I20_ENC_CTL_COUNT_QUADRATURE | M5I20_ENC_CTL_INDEX_ACTIVE_HI | M5I20_ENC_CTL_QUAD_FILTER_4MHZ | M5I20_ENC_CTL_LATCH_ON_READ | M5I20_ENC_CTL_LOCAL_CLEAR; } // Initialize digital I/O. for(i = 0; i < M5I20_NUM_DIGITAL_IO_PORTS; i++){ pCard32->digitalIo[i].data = M5I20_DIGITAL_OUT; pCard32->digitalIo[i].direction = M5I20_DIGITAL_OUT; } pCard16->mode = M5I20_MODE_PWM_ENABLE | M5I20_MODE_COUNTER_ENABLE; return(0);}// FPGA configuration.#include "m5i20_HM5-4E.h"/* * Function: Device_LoadFpga * Purpose: Initialize the FPGA with the contents from compiled in array. * Used by: Local functions. * Returns: Error code. * Notes: * If DONE never goes high, but INIT goes low - this means the FPGA got a valid * synchonization word (5599AA66) but encounterd a CRC error later in the stream. * * If DONE never goes high and INIT stays high, most likely the FPGA never saw * the syncronization word. * */static intDevice_LoadFpga(Device *this){ M5i20HostMotRegMap *pCard16 = this->pCard16; Plx9030LocalRegMap *pBridgeIc = this->pBridgeIc; hal_u32_t i; // Configure the GPIO. pBridgeIc->gpioc &= M5I20_PLX_GPIOC_AND_MASK; pBridgeIc->gpioc |= M5I20_PLX_GPIOC_OR_MASK; // Turn on LED. pBridgeIc->gpioc &= ~M5I20_PLX_GPIOC_LED_OFF; // Reset the FPGA pBridgeIc->gpioc &= ~M5I20_PLX_GPIOC_CFG_NPROGRAM; pBridgeIc->gpioc |= M5I20_PLX_GPIOC_CFG_NWRITE; if(pBridgeIc->gpioc & M5I20_PLX_GPIOC_CFG_DONE){ // Note that if we see DONE at the start of programming, it's most likely due // to an attempt to access the FPGA at the wrong I/O location. rtapi_print_msg(RTAPI_MSG_ERR, "M5I20: ERROR: FPGA busy at start of programming\n"); return(1); } // Enable programming. pBridgeIc->gpioc |= M5I20_PLX_GPIOC_CFG_NPROGRAM; pBridgeIc->gpioc &= ~M5I20_PLX_GPIOC_CFG_NWRITE; // Delay for at least 100 uS. to allow the FPGA to finish its reset sequencing. Device_Delay100us(); // Program the fpga. for(i = 0; i < sizeof(fpgaConfig); i++){ // Write byte to FPGA. pCard16->fpgaCfgData = fpgaConfig[i]; } // Wait for completion of programming. Device_Delay100us(); // Check for completion. if(!(pBridgeIc->gpioc & M5I20_PLX_GPIOC_CFG_DONE)){ rtapi_print_msg(RTAPI_MSG_ERR, "M5I20: ERROR: FPGA programming not completed\n"); return(2); } // Send configuration completion clocks (6 should be enough, but we send // lots for good measure). pBridgeIc->gpioc |= M5I20_PLX_GPIOC_CFG_NWRITE; for(i = 0; i < 24 ; i++){ pCard16->fpgaCfgData = 0xFF; } // Turn off LED. pBridgeIc->gpioc |= M5I20_PLX_GPIOC_LED_OFF; return(0);}static voidDevice_Delay100us(void){ long int maxDelay = rtapi_delay_max(); long int ns = 100000; long int delay; while(ns){ delay = (ns > maxDelay)? maxDelay: ns; ns -= delay; rtapi_delay(delay); }}static intDevice_ExportPinsParametersFunctions(Device *this, int componentId, int boardId){ int msgLevel, error; // This function exports a lot of stuff, which results in a lot of // logging if msg_level is at INFO or ALL. So we save the current value // of msg_level and restore it later. If you actually need to log this // function's actions, change the second line below. msgLevel = rtapi_get_msg_level(); rtapi_set_msg_level(RTAPI_MSG_WARN); // Export encoders. error = Device_ExportEncoderPinsParametersFunctions(this, componentId, boardId); // Export DACs. if(!error) error = Device_ExportDacPinsParametersFunctions(this, componentId, boardId); // Export digital I/O. if(!error) error = Device_ExportDigitalInPinsParametersFunctions(this, componentId, boardId); if(!error) error = Device_ExportDigitalOutPinsParametersFunctions(this, componentId, boardId); // Export miscellaneous. if(!error) error = Device_ExportMiscPinsParametersFunctions(this, componentId, boardId); // Restore saved message level. rtapi_set_msg_level(msgLevel); return(error);}static intDevice_ExportEncoderPinsParametersFunctions(Device *this, int componentId, int boardId){ int halError=0, channel; char name[HAL_NAME_LEN + 2]; // Export pins and parameters. for(channel = 0; channel < M5I20_NUM_ENCODER_CHANNELS; channel++){ // Pins. rtapi_snprintf(name, HAL_NAME_LEN, "m5i20.%d.enc-%02d-count", boardId, channel); if((halError = hal_pin_s32_new(name, HAL_WR, &(this->encoder[channel].pCount), componentId)) != 0) break; rtapi_snprintf(name, HAL_NAME_LEN, "m5i20.%d.enc-%02d-cnt-latch", boardId, channel); if((halError = hal_pin_s32_new(name, HAL_WR, &(this->encoder[channel].pCountLatch), componentId)) != 0) break; rtapi_snprintf(name, HAL_NAME_LEN, "m5i20.%d.enc-%02d-position", boardId, channel); if((halError = hal_pin_float_new(name, HAL_WR, &(this->encoder[channel].pPosition), componentId)) != 0) break; rtapi_snprintf(name, HAL_NAME_LEN, "m5i20.%d.enc-%02d-pos-latch", boardId, channel); if((halError = hal_pin_float_new(name, HAL_WR, &(this->encoder[channel].pPositionLatch), componentId)) != 0) break; rtapi_snprintf(name, HAL_NAME_LEN, "m5i20.%d.enc-%02d-index", boardId, channel); if((halError = hal_pin_bit_new(name, HAL_WR, &(this->encoder[channel].pIndex), componentId)) != 0) break; rtapi_snprintf(name, HAL_NAME_LEN, "m5i20.%d.enc-%02d-idx-latch", boardId, channel); if((halError = hal_pin_bit_new(name, HAL_WR, &(this->encoder[channel].pIndexLatch), componentId)) != 0) break; rtapi_snprintf(name, HAL_NAME_LEN, "m5i20.%d.enc-%02d-latch-index", boardId, channel); if((halError = hal_pin_bit_new(name, HAL_RD_WR, &(this->encoder[channel].pLatchIndex), componentId)) != 0) break; rtapi_snprintf(name, HAL_NAME_LEN, "m5i20.%d.enc-%02d-reset-count", boardId, channel); if((halError = hal_pin_bit_new(name, HAL_RD_WR, &(this->encoder[channel].pResetCount), componentId)) != 0) break; // Parameters. rtapi_snprintf(name, HAL_NAME_LEN, "m5i20.%d.enc-%02d-scale", boardId, channel); if((halError = hal_param_float_new(name, HAL_WR, &(this->encoder[channel].scale), componentId)) != 0) break; // Init encoder. *(this->encoder[channel].pCount) = 0; *(this->encoder[channel].pCountLatch) = 0; *(this->encoder[channel].pPosition) = 0.0; *(this->encoder[channel].pPositionLatch) = 0.0; *(this->encoder[channel].pIndex) = 0; *(this->encoder[channel].pIndexLatch) = 0; *(this->encoder[channel].pLatchIndex) = 0; *(this->encoder[channel].pResetCount) = 0; this->encoder[channel].scale = 1.0; } // Export functions. if(!halError){ rtapi_snprintf(name, HAL_NAME_LEN, "m5i20.%d.encoder-read", boardId); halError = hal_export_funct(name, Device_EncoderRead, this, 1, 0, componentId); } if(halError){ rtapi_print_msg(RTAPI_MSG_ERR, "M5I20: ERROR: export encoder failed\n"); return(-1); } return(0);}static intDevice_ExportDacPinsParametersFunctions(Device *this, int componentId, int boardId){ int halError=0, channel; char name[HAL_NAME_LEN + 2]; // Export pins and parameters. for(channel = 0; channel < M5I20_NUM_PWM_CHANNELS; channel++){ // Pins. rtapi_snprintf(name, HAL_NAME_LEN, "m5i20.%d.dac-%02d-enable", boardId, channel); if((halError = hal_pin_bit_new(name, HAL_RD, &(this->dac[channel].pEnable), componentId)) != 0) break; rtapi_snprintf(name, HAL_NAME_LEN, "m5i20.%d.dac-%02d-value", boardId, channel); if((halError = hal_pin_float_new(name, HAL_RD, &(this->dac[channel].pValue), componentId)) != 0) break; // Parameters. rtapi_snprintf(name, HAL_NAME_LEN, "m5i20.%d.dac-%02d-offset", boardId, channel); if((halError = hal_param_float_new(name, HAL_WR, &(this->dac[channel].offset), componentId)) != 0) break; rtapi_snprintf(name, HAL_NAME_LEN, "m5i20.%d.dac-%02d-gain", boardId, channel); if((halError = hal_param_float_new(name, HAL_WR, &(this->dac[channel].gain), componentId)) != 0) break; rtapi_snprintf(name, HAL_NAME_LEN, "m5i20.%d.dac-%02d-interlaced", boardId, channel); if((halError = hal_param_bit_new(name, HAL_WR, &(this->dac[channel].interlaced), componentId)) != 0) break; // Init DAC. *(this->dac[channel].pEnable) = 0; *(this->dac[channel].pValue) = 0.0; this->dac[channel].offset = 0.0; this->dac[channel].gain = 1.0; this->dac[channel].interlaced = 1; } // Export functions. if(!halError){ rtapi_snprintf(name, HAL_NAME_LEN, "m5i20.%d.dac-write", boardId); halError = hal_export_funct(name, Device_DacWrite, this, 1, 0, componentId); } if(halError){ rtapi_print_msg(RTAPI_MSG_ERR, "M5I20: ERROR: export DAC failed\n"); return(-1); } return(0);}static intDevice_ExportDigitalInPinsParametersFunctions(Device *this, int componentId, int boardId){ int halError=0, channel; char name[HAL_NAME_LEN + 2]; // Export pins and parameters. for(channel = 0; channel < M5I20_NUM_DIGITAL_INPUTS; channel++){ // Pins. rtapi_snprintf(name, HAL_NAME_LEN, "m5i20.%d.in-%02d", boardId, channel); if((halError = hal_pin_bit_new(name, HAL_WR, &(this->in[channel].pValue), componentId)) != 0) break; rtapi_snprintf(name, HAL_NAME_LEN, "m5i20.%d.in-%02d-not", boardId, channel); if((halError = hal_pin_bit_new(name, HAL_WR, &(this->in[channel].pValueNot), componentId)) != 0) break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -