⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hostmot2.c

📁 CNC 的开放码,EMC2 V2.2.8版
💻 C
📖 第 1 页 / 共 3 页
字号:
////    Copyright (C) 2007-2008 Sebastian Kuzminsky////    This program is free software; you can redistribute it and/or modify//    it under the terms of the GNU General Public License as published by//    the Free Software Foundation; either version 2 of the License, or//    (at your option) any later version.////    This program is distributed in the hope that it will be useful,//    but WITHOUT ANY WARRANTY; without even the implied warranty of//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the//    GNU General Public License for more details.////    You should have received a copy of the GNU General Public License//    along with this program; if not, write to the Free Software//    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA//#include <linux/slab.h>#include <linux/ctype.h>#include "rtapi.h"#include "rtapi_app.h"#include "rtapi_string.h"#include "rtapi_math.h"#include "hal.h"#include "hostmot2.h"#include "bitfile.h"MODULE_INFO(emc2, "component:hostmot2:RTAI driver for the HostMot2 firmware from Mesa Electronics.");MODULE_INFO(emc2, "funct:read:1:Read all registers.");MODULE_INFO(emc2, "funct:write:1:Write all registers.");MODULE_INFO(emc2, "funct:pet_watchdog:0:Pet the watchdog to keep it from biting us for a while.");MODULE_INFO(emc2, "license:GPL");MODULE_LICENSE("GPL");int debug_idrom = 0;RTAPI_MP_INT(debug_idrom, "Developer/debug use only!  Enable debug logging of the HostMot2\nIDROM header.");int debug_module_descriptors = 0;RTAPI_MP_INT(debug_module_descriptors, "Developer/debug use only!  Enable debug logging of the HostMot2\nModule Descriptors.");int debug_modules = 0;RTAPI_MP_INT(debug_modules, "Developer/debug use only!  Enable debug logging of the HostMot2\nModules used.");// this keeps track of all the hm2 instances that have been registered by// the low-level driversstruct list_head hm2_list;static int comp_id;// // functions exported to EMC// static void hm2_read(void *void_hm2, long period) {    hostmot2_t *hm2 = void_hm2;    // if there are comm problems, wait for the user to fix it    if ((*hm2->llio->io_error) != 0) return;    // if the watchdog has bit, wait for the user to reset it    if ((hm2->watchdog.num_instances == 1) && (*hm2->watchdog.instance[0].hal.pin.has_bit != 0)) return;    hm2_tram_read(hm2);    if ((*hm2->llio->io_error) != 0) return;    hm2_ioport_gpio_process_tram_read(hm2);    hm2_encoder_process_tram_read(hm2, period);    hm2_stepgen_process_tram_read(hm2, period);    hm2_raw_read(hm2);}static void hm2_write(void *void_hm2, long period) {    hostmot2_t *hm2 = void_hm2;    // if there are comm problems, wait for the user to fix it    if ((*hm2->llio->io_error) != 0) return;    // if the watchdog has bit, wait for the user to reset it    if ((hm2->watchdog.num_instances == 1) && (*hm2->watchdog.instance[0].hal.pin.has_bit != 0)) return;    hm2_ioport_gpio_prepare_tram_write(hm2);    hm2_pwmgen_prepare_tram_write(hm2);    hm2_stepgen_prepare_tram_write(hm2, period);    hm2_tram_write(hm2);    // these usually do nothing    // they only write to the FPGA if certain pins & params have changed    hm2_ioport_write(hm2);    // handles gpio.is_output but not gpio.out (that's done in tram_write() above)    hm2_watchdog_write(hm2);  // in case the user has written to the watchdog.timeout_ns param    hm2_pwmgen_write(hm2);    // update pwmgen registers if needed     hm2_stepgen_write(hm2);   // update stepgen registers if needed     hm2_encoder_write(hm2);   // update ctrl register if needed     hm2_raw_write(hm2);}static void hm2_read_gpio(void *void_hm2, long period) {    hostmot2_t *hm2 = void_hm2;    // if there are comm problems, wait for the user to fix it    if ((*hm2->llio->io_error) != 0) return;    // if the watchdog has bit, wait for the user to reset it    if ((hm2->watchdog.num_instances == 1) && (*hm2->watchdog.instance[0].hal.pin.has_bit != 0)) return;    hm2_ioport_gpio_read(hm2);}static void hm2_write_gpio(void *void_hm2, long period) {    hostmot2_t *hm2 = void_hm2;    // if there are comm problems, wait for the user to fix it    if ((*hm2->llio->io_error) != 0) return;    // if the watchdog has bit, wait for the user to reset it    if ((hm2->watchdog.num_instances == 1) && (*hm2->watchdog.instance[0].hal.pin.has_bit != 0)) return;    hm2_ioport_gpio_write(hm2);}// // misc little helper functions//// FIXME: the static automatic string makes this function non-reentrantconst char *hm2_hz_to_mhz(u32 freq_hz) {    static char mhz_str[20];    int freq_mhz, freq_mhz_fractional;    freq_mhz = freq_hz / (1000*1000);    freq_mhz_fractional = (freq_hz / 1000) % 1000;    sprintf(mhz_str, "%d.%03d", freq_mhz, freq_mhz_fractional);    return mhz_str;}// FIXME: the static automatic string makes this function non-reentrantconst char *hm2_get_general_function_name(int gtag) {    switch (gtag) {         case HM2_GTAG_WATCHDOG:        return "Watchdog";        case HM2_GTAG_IOPORT:          return "IOPort";        case HM2_GTAG_ENCODER:         return "Encoder";        case HM2_GTAG_STEPGEN:         return "StepGen";        case HM2_GTAG_PWMGEN:          return "PWMGen";        case HM2_GTAG_TRANSLATIONRAM:  return "TranslationRAM";        default: {            static char unknown[100];            rtapi_snprintf(unknown, 100, "(unknown-gtag-%d)", gtag);            return unknown;        }    }}static int hm2_parse_config_string(hostmot2_t *hm2, char *config_string) {    // default is to enable everything in the firmware    hm2->config.num_encoders = -1;    hm2->config.num_pwmgens = -1;    hm2->config.num_stepgens = -1;    hm2->config.enable_raw = 0;    hm2->config.firmware = NULL;    if (config_string == NULL) return 0;    DBG("parsing config string \"%s\"\n", config_string);    do {        char *token;        char *endp;        token = strsep(&config_string, " ");        if (token == NULL) break;        if (token[0] == '\0') {            if ((config_string == NULL) || (config_string[0] == '\0')) break;            continue;        }        if (strncmp(token, "num_encoders=", 13) == 0) {            token += 13;            hm2->config.num_encoders = simple_strtol(token, &endp, 0);        } else if (strncmp(token, "num_pwmgens=", 12) == 0) {            token += 12;            hm2->config.num_pwmgens = simple_strtol(token, &endp, 0);        } else if (strncmp(token, "num_stepgens=", 13) == 0) {            token += 13;            hm2->config.num_stepgens = simple_strtol(token, &endp, 0);        } else if (strncmp(token, "enable_raw", 10) == 0) {            token += 10;            hm2->config.enable_raw = 1;        } else if (strncmp(token, "firmware=", 9) == 0) {            hm2->config.firmware = token + 9;        } else {            ERR("invalid token in config string: \"%s\"\n", token);            return -EINVAL;        }    } while (1);    DBG("final config:\n");    DBG("    num_encoders=%d\n", hm2->config.num_encoders);    DBG("    num_pwmgens=%d\n",  hm2->config.num_pwmgens);    DBG("    num_stepgens=%d\n", hm2->config.num_stepgens);    DBG("    enable_raw=%d\n",   hm2->config.enable_raw);    DBG("    firmware=%s\n",   hm2->config.firmware ? hm2->config.firmware : "(NULL)");    return 0;}// // functions for dealing with the idrom// static void hm2_print_idrom(hostmot2_t *hm2) {    PRINT("IDRom:\n");     if (hm2->idrom.idrom_type == 2) {        PRINT("    IDRom Type: 0x%08X\n", hm2->idrom.idrom_type);     } else {        PRINT("    IDRom Type: 0x%08X ***** Expected 2!  Continuing anyway! *****\n", hm2->idrom.idrom_type);     }    if (hm2->idrom.offset_to_modules == 0x40) {        PRINT("    Offset to Modules: 0x%08X\n", hm2->idrom.offset_to_modules);     } else {        PRINT("    Offset to Modules: 0x%08X ***** Expected 0x40!  Continuing anyway *****\n", hm2->idrom.offset_to_modules);     }    if (hm2->idrom.offset_to_pin_desc == 0x200) {        PRINT("    Offset to Pin Description: 0x%08X\n", hm2->idrom.offset_to_pin_desc);     } else {        PRINT("    Offset to Pin Description: 0x%08X ***** Expected 0x200!  Continuing anyway! *****\n", hm2->idrom.offset_to_pin_desc);     }    PRINT(        "    Board Name: %c%c%c%c%c%c%c%c\n",        hm2->idrom.board_name[0],        hm2->idrom.board_name[1],        hm2->idrom.board_name[2],        hm2->idrom.board_name[3],        hm2->idrom.board_name[4],        hm2->idrom.board_name[5],        hm2->idrom.board_name[6],        hm2->idrom.board_name[7]    );     PRINT("    FPGA Size: %u\n", hm2->idrom.fpga_size);     PRINT("    FPGA Pins: %u\n", hm2->idrom.fpga_pins);     PRINT("    IO Ports: %u\n", hm2->idrom.io_ports);     PRINT("    IO Width: %u\n", hm2->idrom.io_width);     if (hm2->idrom.port_width == 24) {        PRINT("    Port Width: %u\n", hm2->idrom.port_width);     } else {        PRINT("    Port Width: %u ***** Expected 24!  Continuing anyway! *****\n", hm2->idrom.port_width);     }    PRINT(        "    Clock Low: %d Hz (%d KHz, %d MHz)\n",        hm2->idrom.clock_low,        (hm2->idrom.clock_low / 1000),        (hm2->idrom.clock_low / (1000 * 1000))    );     PRINT(        "    Clock High: %d Hz (%d KHz, %d MHz)\n",        hm2->idrom.clock_high,        (hm2->idrom.clock_high / 1000),        (hm2->idrom.clock_high / (1000 * 1000))    );     PRINT("    Instance Stride 0: 0x%08X\n", hm2->idrom.instance_stride_0);     PRINT("    Instance Stride 1: 0x%08X\n", hm2->idrom.instance_stride_1);     PRINT("    Register Stride 0: 0x%08X\n", hm2->idrom.register_stride_0);     PRINT("    Register Stride 1: 0x%08X\n", hm2->idrom.register_stride_1); }static int hm2_read_idrom(hostmot2_t *hm2) {    //     // find the idrom offset    //     if (!hm2->llio->read(hm2->llio, HM2_ADDR_IDROM_OFFSET, &hm2->idrom_offset, 2)) {        ERR("error reading IDROM Offset\n");        return -EIO;    }    //     // first read in the idrom type to make sure we know how to deal with it    //        if (!hm2->llio->read(hm2->llio, hm2->idrom_offset, &hm2->idrom.idrom_type, sizeof(hm2->idrom.idrom_type))) {        ERR("error reading IDROM type\n");         return -EIO;    }    if (hm2->idrom.idrom_type != 2) {        ERR("invalid IDROM type %d, expected 2, aborting load\n", hm2->idrom.idrom_type);         return -EINVAL;    }    //     // ok, read in the whole thing    //        if (!hm2->llio->read(hm2->llio, hm2->idrom_offset, &hm2->idrom, sizeof(hm2->idrom))) {        ERR("error reading IDROM\n");         return -EIO;    }    //    // verify the idrom we read    //    if (hm2->idrom.port_width != 24) {        ERR("invalid IDROM PortWidth %d, expected 24, aborting load\n", hm2->idrom.port_width);         hm2_print_idrom(hm2);        return -EINVAL;    }    if (hm2->idrom.io_width != (hm2->idrom.io_ports * hm2->idrom.port_width)) {        ERR(            "IDROM IOWidth is %d, but IDROM IOPorts is %d and IDROM PortWidth is %d (inconsistent firmware), aborting driver load\n",            hm2->idrom.io_width,            hm2->idrom.io_ports,            hm2->idrom.port_width        );        return -EINVAL;    }    if (hm2->idrom.io_ports != hm2->llio->num_ioport_connectors) {        ERR(            "IDROM IOPorts is %d but llio num_ioport_connectors is %d, driver and firmware are inconsistent, aborting driver load\n",            hm2->idrom.io_ports,            hm2->llio->num_ioport_connectors        );        return -EINVAL;    }    if (hm2->idrom.clock_low < 1e6) {        ERR(            "IDROM ClockLow is %d, that's too low, aborting driver load\n",            hm2->idrom.clock_low        );        return -EINVAL;    }    if (hm2->idrom.clock_high < 1e6) {        ERR(            "IDROM ClockHigh is %d, that's too low, aborting driver load\n",            hm2->idrom.clock_high        );        return -EINVAL;    }    if (debug_idrom) {        hm2_print_idrom(hm2);    }    return 0;}// reads the Module Descriptors// doesnt do any validation or parsing or anything, that's in hm2_parse_module_descriptors(), which comes nextstatic int hm2_read_module_descriptors(hostmot2_t *hm2) {    int addr = hm2->idrom_offset + hm2->idrom.offset_to_modules;    for (        hm2->num_mds = 0;        hm2->num_mds < HM2_MAX_MODULE_DESCRIPTORS;        hm2->num_mds ++, addr += 12    ) {        u32 d[3];        hm2_module_descriptor_t *md = &hm2->md[hm2->num_mds];        if (!hm2->llio->read(hm2->llio, addr, d, 12)) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -