Esempio n. 1
0
// this is the function exported to HAL
// it keeps the watchdog from biting us for a while
static int hm2_pet_watchdog(void *void_hm2, const hal_funct_args_t *fa) {
    hostmot2_t *hm2 = void_hm2;
    static int print_warning = 1;

    if (print_warning) {
        HM2_PRINT("The hm2 pet_watchdog function is no longer needed.\n");
        HM2_PRINT("The hm2 write function now pets the watchdog.\n");
        print_warning = 0;
    }
    return 0;
}
// this is the function exported to HAL
// it keeps the watchdog from biting us for a while
static void hm2_pet_watchdog(void *void_hm2, long period_ns) {
    hostmot2_t *hm2 = void_hm2;


    // if there is no watchdog, then there's nothing to do
    if (hm2->watchdog.num_instances == 0) return;

    // if there are comm problems, wait for the user to fix it
    if ((*hm2->llio->io_error) != 0) return;

    // if the requested timeout is dangerously short compared to the petting-period, warn the user once
    if (hm2->watchdog.instance[0].hal.param.timeout_ns < (1.5 * period_ns)) {
        if (0 == hm2->watchdog.instance[0].warned_about_short_timeout) {
            hm2->watchdog.instance[0].warned_about_short_timeout = 1;
            HM2_PRINT(
                "Watchdog timeout (%u ns) is dangerously short compared to pet_watchdog() period (%ld ns)\n",
                hm2->watchdog.instance[0].hal.param.timeout_ns,
                period_ns
            );
        }
    }

    // if the watchdog has bit, wait for the user to reset it
    if (*hm2->watchdog.instance[0].hal.pin.has_bit) return;

    // petting the watchdog wakes it up, and now we can't stop or it will bite!
    hm2->watchdog.instance[0].enable = 1;

    if (hm2->llio->needs_reset) {
        // user has cleared the bit
        HM2_PRINT("trying to recover from IO error or Watchdog bite\n");

        // reset the watchdog status
        hm2->watchdog.status_reg[0] = 0;

        // write all settings out to the FPGA
        hm2_force_write(hm2);
        if ((*hm2->llio->io_error) != 0) {
            HM2_PRINT("error recovery failed\n");
            return;
        }
        HM2_PRINT("error recover successful!\n");

        hm2->llio->needs_reset = 0;
    }


    // reset the watchdog timer
    // FIXME: write just 1 byte
    hm2->llio->write(hm2->llio, hm2->watchdog.reset_addr, hm2->watchdog.reset_reg, (hm2->watchdog.num_instances * sizeof(u32)));
}
Esempio n. 3
0
// if the user has changed the timeout, sync it out to the watchdog
void hm2_watchdog_write(hostmot2_t *hm2, long period_ns) {
    if (hm2->watchdog.num_instances != 1) return;

    // 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.instance[0].hal.pin.has_bit) return;

    // writing to the watchdog wakes it up, and now we can't stop or it will bite!
    hm2->watchdog.instance[0].enable = 1;

    if (hm2->llio->needs_reset) {
        // user has cleared the bit
        HM2_PRINT("trying to recover from IO error or Watchdog bite\n");

        // reset the watchdog status
        hm2->watchdog.status_reg[0] = 0;

        // write all settings out to the FPGA
        hm2_force_write(hm2);
        if ((*hm2->llio->io_error) != 0) {
            HM2_PRINT("error recovery failed\n");
            return;
        }
        HM2_PRINT("error recover successful!\n");

        hm2->llio->needs_reset = 0;
    }

    if (
        (hm2->watchdog.instance[0].hal.param.timeout_ns == hm2->watchdog.instance[0].written_timeout_ns)
        &&
        (hm2->watchdog.instance[0].enable == hm2->watchdog.instance[0].written_enable)
    ) {
        return;
    }

    // if the requested timeout is dangerously short compared to the petting-period, warn the user once
    if (hm2->watchdog.instance[0].hal.param.timeout_ns < (1.5 * period_ns)) {
        HM2_PRINT(
            "Watchdog timeout (%u ns) is dangerously short compared to hm2_write() period (%ld ns)\n",
            hm2->watchdog.instance[0].hal.param.timeout_ns,
            period_ns
        );
    }

    hm2_watchdog_force_write(hm2);
}
void hm2_watchdog_print_module(hostmot2_t *hm2) {
    int i;
    HM2_PRINT("Watchdog: %d\n", hm2->watchdog.num_instances);
    if (hm2->watchdog.num_instances <= 0) return;
    HM2_PRINT("    clock_frequency: %d Hz (%s MHz)\n", hm2->watchdog.clock_frequency, hm2_hz_to_mhz(hm2->watchdog.clock_frequency));
    HM2_PRINT("    version: %d\n", hm2->watchdog.version);
    HM2_PRINT("    timer_addr: 0x%04X\n", hm2->watchdog.timer_addr);
    HM2_PRINT("    status_addr: 0x%04X\n", hm2->watchdog.status_addr);
    HM2_PRINT("    reset_addr: 0x%04X\n", hm2->watchdog.reset_addr);
    for (i = 0; i < hm2->watchdog.num_instances; i ++) {
        HM2_PRINT("    instance %d:\n", i);
        HM2_PRINT("        param timeout_ns = %u\n", hm2->watchdog.instance[i].hal.param.timeout_ns);
        HM2_PRINT("        pin has_bit = %d\n", (*hm2->watchdog.instance[i].hal.pin.has_bit));
        HM2_PRINT("        reg timer = 0x%08X\n", hm2->watchdog.timer_reg[i]);
    }
}
Esempio n. 5
0
void hm2_print_pin_usage(hostmot2_t *hm2) {
    int i;

    HM2_PRINT("%d I/O Pins used:\n", hm2->num_pins);

    for (i = 0; i < hm2->num_pins; i ++) {
        
        hm2_pin_t *pin = &(hm2->pin[i]);
        
        if (pin->gtag == pin->sec_tag) {
            if(pin->sec_unit & 0x80)
                HM2_PRINT(
                    "    IO Pin %03d (%s-%02d): %s (all), pin %s (%s)\n",
                    i,
                    hm2->llio->ioport_connector_name[pin->port_num],
                    pin->port_pin,
                    hm2_get_general_function_name(pin->gtag),
                    hm2_get_pin_secondary_name(&hm2->pin[i]),
                    ((pin->sec_pin & 0x80) ? "Output" : "Input")
                );
            else
                HM2_PRINT(
                    "    IO Pin %03d (%s-%02d): %s #%d, pin %s (%s)\n",
                    i,
                    hm2->llio->ioport_connector_name[pin->port_num],
                    pin->port_pin,
                    hm2_get_general_function_name(pin->gtag),
                    pin->sec_unit,
                    hm2_get_pin_secondary_name(pin),
                    ((pin->sec_pin & 0x80) ? "Output" : "Input")
                );
        } else {
            HM2_PRINT(
                "    IO Pin %03d (%s-%02d): %s\n",
                i,
                hm2->llio->ioport_connector_name[pin->port_num],
                pin->port_pin,
                hm2_get_general_function_name(pin->gtag)
            );
        }
    }
}
Esempio n. 6
0
static void hm2_print_pin_descriptors(hostmot2_t *hm2) {
    int i;

    HM2_PRINT("%d HM2 Pin Descriptors:\n", hm2->num_pins);

    for (i = 0; i < hm2->num_pins; i ++) {
        HM2_PRINT("    pin %d:\n", i);
        HM2_PRINT(
            "        Primary Tag: 0x%02X (%s)\n",
            hm2->pin[i].primary_tag,
            hm2_get_general_function_name(hm2->pin[i].primary_tag)
        );
        if (hm2->pin[i].sec_tag != 0) {
            HM2_PRINT(
                "        Secondary Tag: 0x%02X (%s)\n",
                hm2->pin[i].sec_tag,
                hm2_get_general_function_name(hm2->pin[i].sec_tag)
            );
            HM2_PRINT("        Secondary Unit: 0x%02X\n", hm2->pin[i].sec_unit);
            HM2_PRINT(
                "        Secondary Pin: 0x%02X (%s, %s)\n",
                hm2->pin[i].sec_pin,
                hm2_get_pin_secondary_name(&hm2->pin[i]),
                ((hm2->pin[i].sec_pin & 0x80) ? "Output" : "Input")
            );
        }
    }
}
Esempio n. 7
0
void hm2_resolver_print_module(hostmot2_t *hm2) {
    int i;
    HM2_PRINT("resolvers: %d\n", hm2->resolver.num_instances);
    if (hm2->resolver.num_instances <= 0) return;
    HM2_PRINT("    clock_frequency: %d Hz (%s MHz)\n",
              hm2->resolver.clock_frequency,
              hm2_hz_to_mhz(hm2->resolver.clock_frequency));
    HM2_PRINT("    version: %d\n", hm2->resolver.version);
    HM2_PRINT("    position_addr: 0x%04X\n", hm2->resolver.position_addr);
    HM2_PRINT("    velocity_addr: 0x%04X\n", hm2->resolver.velocity_addr);
    for (i = 0; i < hm2->resolver.num_instances; i ++) {
        HM2_PRINT("    instance %d:\n", i);
        HM2_PRINT("        hw:\n");
        HM2_PRINT("            position = %08x\n",
                  (hm2->resolver.position_reg[i]));
        HM2_PRINT("            velocity = %08x\n",
                  (hm2->resolver.velocity_reg[i]));
    }
}
Esempio n. 8
0
void hm2_bspi_print_module(hostmot2_t *hm2){
    int i,j;
    HM2_PRINT("Buffered SPI: %d\n", hm2->bspi.num_instances);
    if (hm2->bspi.num_instances <= 0) return;
    HM2_PRINT("    version: %d\n", hm2->bspi.version);
    HM2_PRINT("    channel configurations\n");
    for (i = 0; i < hm2->bspi.num_instances; i ++) {
        HM2_PRINT("    clock_frequency: %d Hz (%s MHz)\n", 
                  hm2->bspi.instance[i].clock_freq, 
                  hm2_hz_to_mhz(hm2->bspi.instance[i].clock_freq));
        HM2_PRINT("    instance %d:\n", i);
        HM2_PRINT("    HAL name = %s\n", hm2->bspi.instance[i].name);
        for (j = 0; j < 16 ; j++){
            HM2_PRINT("         frame %i config = %08x\n", j, 
                      hm2->bspi.instance[i].cd[j]);
            HM2_PRINT("                address = %08x\n", 
                      hm2->bspi.instance[i].addr[j]);
        }
    }
}
Esempio n. 9
0
void hm2_uart_print_module(hostmot2_t *hm2){
    int i;
    HM2_PRINT("UART: %d\n", hm2->uart.num_instances);
    if (hm2->uart.num_instances <= 0) return;
    HM2_PRINT("    version: %d\n", hm2->uart.version);
    HM2_PRINT("    channel configurations\n");
    for (i = 0; i < hm2->uart.num_instances; i ++) {
        HM2_PRINT("    clock_frequency: %d Hz (%s MHz)\n", 
                  hm2->uart.instance[i].clock_freq, 
                  hm2_hz_to_mhz(hm2->uart.instance[i].clock_freq));
        HM2_PRINT("    instance %d:\n", i);
        HM2_PRINT("    HAL name = %s\n", hm2->uart.instance[i].name);
    }
}
Esempio n. 10
0
void hm2_watchdog_process_tram_read(hostmot2_t *hm2) {
    // if there is no watchdog, then there's nothing to do
    if (hm2->watchdog.num_instances == 0) return;

    // if there are comm problems, wait for the user to fix it
    if ((*hm2->llio->io_error) != 0) return;

    // if we've already noticed the board needs to be reset, don't re-read
    // the watchdog has-bit bit
    // Note: we check needs_reset instead of the has-bit pin here, because
    // has-bit might be cleared by the user at any time, so using it here
    // would cause a race condition between this function and pet_watchdog
    if (hm2->llio->needs_reset != 0) return;

    // last time we were here, everything was fine
    // see if the watchdog has bit since then
    if (hm2->watchdog.status_reg[0] & 0x1) {
        HM2_PRINT("Watchdog has bit! (set the .has-bit pin to False to resume)\n");
        *hm2->watchdog.instance[0].hal.pin.has_bit = 1;
        hm2->llio->needs_reset = 1;
    }
}
Esempio n. 11
0
int sslbp_flash(char *fname){
    const struct rtapi_firmware *fw;
    struct rtapi_device dev;
    int r;
    int write_sz, erase_sz;
    
    if (strstr("8i20", remote->name)){
        if (hm2->sserial.version < 37){
            rtapi_print("SSLBP Version must be at least v37 to flash the 8i20"
                        "This firmware has v%i. Sorry about that\n"
                        ,hm2->sserial.version);
            return -1;
        }
    }
    else if (hm2->sserial.version < 34){
        rtapi_print("SSLBP Version must be at least v34. This firmware has v%i"
                    "\n",hm2->sserial.version);
        return -1;
    }
    
    if (hm2->sserial.baudrate != 115200){
        rtapi_print("To flash firmware the baud rate of the board must be set "
                    "to 115200 by jumper, and in Hostmot2 using the "
                    "sserial_baudrate modparam\n");
        return -1;
    }
     
    //Copied direct from hostmot2.c. A bit of a faff, but seems to be necessary. 
    memset(&dev, '\0', sizeof(dev));
    rtapi_dev_set_name(&dev, hm2->llio->name);
    dev.release = setsserial_release;
    r = rtapi_device_register(&dev);
    if (r != 0) {
        HM2_ERR("error with device_register\n");
        return -1;
    }
    r = rtapi_request_firmware(&fw, fname, &dev);
    rtapi_device_unregister(&dev);
    if (r == -ENOENT) {
        HM2_ERR("firmware %s not found\n",fname);
        return -1;
    }
    if (r != 0) {
        HM2_ERR("request for firmware %s failed, aborting\n", fname);
        return -1;
    }    
    rtapi_print("Firmware size 0x%zx\n", fw->size);
    
    if (setup_start() < 0) goto fail0;
    flash_start();
    write_sz = 1 << sslbp_read_byte(LBPFLASHWRITESIZELOC);
    erase_sz = 1 << sslbp_read_byte(LBPFLASHERASESIZELOC);
    HM2_PRINT("Write Size = %x, Erase Size = %x\n", write_sz, erase_sz);
    flash_stop();
    
    //Programming Loop
    {
        int ReservedBlock = 0;
        int StartBlock = ReservedBlock + 1;
        
        int blocknum = StartBlock;
        int block_start;
        int i, j, t;
        while (blocknum * erase_sz < fw->size){
            block_start = blocknum * erase_sz;
            for (t = 0; t < erase_sz && fw->data[block_start + t] == 0 ; t++){ }
            if (t <  erase_sz){ // found a non-zero byte
                flash_start();
                sslbp_write_long(LBPFLASHOFFSETLOC, block_start);
                sslbp_write_byte(LBPFLASHCOMMITLOC, FLASHERASE_CMD);
                if (sslbp_read_cookie() != LBPCOOKIE){
                    HM2_ERR("Synch failed during block erase: aborting\n");
                    goto fail0;
                }
                flash_stop();
                HM2_PRINT("Erased block %i\n", blocknum);
                flash_start();
                for (i = 0; i < erase_sz ; i += write_sz){
                    sslbp_write_long(LBPFLASHOFFSETLOC, block_start + i);
                    for (j = 0 ; j < write_sz ; j += 8){
                        rtapi_u32 data0, data1, m;
                        m = block_start + i + j;
                        data0 = (fw->data[m] 
                              + (fw->data[m + 1] << 8)
                              + (fw->data[m + 2] << 16)
                              + (fw->data[m + 3] << 24));
                        data1 = (fw->data[m + 4] 
                              + (fw->data[m + 5] << 8)
                              + (fw->data[m + 6] << 16)
                              + (fw->data[m + 7] << 24));
                        sslbp_write_double(j, data0, data1);
                    }
                    sslbp_write_byte(LBPFLASHCOMMITLOC, FLASHWRITE_CMD);
                    if (sslbp_read_cookie() != LBPCOOKIE){
                        HM2_ERR("Synch failed during block write: aborting\n");
                        goto fail0;
                    }
                }
                flash_stop();
                HM2_PRINT("Wrote block %i\n", blocknum);
            }
            else // Looks like an all-zeros block
            { 
                HM2_PRINT("Skipped Block %i\n", blocknum);
            }
            blocknum++;
        }
    }
    
    rtapi_release_firmware(fw);
    
    return 0;
    
fail0:
    flash_stop();
    return -1;
}
Esempio n. 12
0
int hm2_bspi_parse_md(hostmot2_t *hm2, int md_index) 
{
    // All this function actually does is allocate memory
    // and give the bspi modules names. 
    
    
    // 
    // some standard sanity checks
    //
    
    int i, j, r = -EINVAL;
    hm2_module_descriptor_t *md = &hm2->md[md_index];
    
    if (!hm2_md_is_consistent_or_complain(hm2, md_index, 0, 3, 0x40, 0x0007)) {
        HM2_ERR("inconsistent Module Descriptor!\n");
        return -EINVAL;
    }
    
    if (hm2->bspi.num_instances != 0) {
        HM2_ERR(
                "found duplicate Module Descriptor for %s (inconsistent "
                "firmware), not loading driver\n",
                hm2_get_general_function_name(md->gtag)
                );
        return -EINVAL;
    }
    
    if (hm2->config.num_bspis > md->instances) {
        HM2_ERR(
                "config defines %d bspis, but only %d are available, "
                "not loading driver\n",
                hm2->config.num_bspis,
                md->instances
                );
        return -EINVAL;
    }
    
    if (hm2->config.num_bspis == 0) {
        return 0;
    }
    
    // 
    // looks good, start initializing
    // 
    
    if (hm2->config.num_bspis == -1) {
        hm2->bspi.num_instances = md->instances;
    } else {
        hm2->bspi.num_instances = hm2->config.num_bspis;
    }
    
    hm2->bspi.instance = (hm2_bspi_instance_t *)hal_malloc(hm2->bspi.num_instances 
                                                     * sizeof(hm2_bspi_instance_t));
    if (hm2->bspi.instance == NULL) {
        HM2_ERR("out of memory!\n");
        r = -ENOMEM;
        goto fail0;
    }
    
    for (i = 0 ; i < hm2->bspi.num_instances ; i++){
        hm2_bspi_instance_t *chan = &hm2->bspi.instance[i];
        chan->clock_freq = md->clock_freq;
        r = sprintf(chan->name, "%s.bspi.%01d", hm2->llio->name, i);
        HM2_PRINT("created Buffered SPI function %s.\n", chan->name);
        chan->base_address = md->base_address + i * md->instance_stride;
        chan->register_stride = md->register_stride;
        chan->instance_stride = md->instance_stride;
        chan->cd_addr = md->base_address + md->register_stride + i * sizeof(rtapi_u32);
        chan->count_addr = md->base_address + 2 * md->register_stride + i * sizeof(rtapi_u32);
        for (j = 0 ; j < 16 ; j++ ){
            chan->addr[j] = chan->base_address + j * sizeof(rtapi_u32);
        }
        
    }
    return hm2->bspi.num_instances;
fail0:
    return r;
}
Esempio n. 13
0
int hm2_watchdog_parse_md(hostmot2_t *hm2, int md_index) {
    hm2_module_descriptor_t *md = &hm2->md[md_index];
    int r;


    // 
    // some standard sanity checks
    //

    if (!hm2_md_is_consistent_or_complain(hm2, md_index, 0, 3, 4, 0)) {
        HM2_ERR("inconsistent Module Descriptor!\n");
        return -EINVAL;
    }

    if (hm2->watchdog.num_instances != 0) {
        HM2_ERR(
            "found duplicate Module Descriptor for %s (inconsistent firmware), not loading driver\n",
            hm2_get_general_function_name(md->gtag)
        );
        return -EINVAL;
    }


    // 
    // special sanity checks for watchdog
    //

    if (md->instances != 1) {
        HM2_PRINT("MD declares %d watchdogs!  only using the first one...\n", md->instances);
    }


    // 
    // looks good, start initializing
    // 


    hm2->watchdog.num_instances = 1;

    hm2->watchdog.instance = (hm2_watchdog_instance_t *)hal_malloc(hm2->watchdog.num_instances * sizeof(hm2_watchdog_instance_t));
    if (hm2->watchdog.instance == NULL) {
        HM2_ERR("out of memory!\n");
        r = -ENOMEM;
        goto fail0;
    }

    hm2->watchdog.clock_frequency = md->clock_freq;
    hm2->watchdog.version = md->version;

    hm2->watchdog.timer_addr = md->base_address + (0 * md->register_stride);
    hm2->watchdog.status_addr = md->base_address + (1 * md->register_stride);
    hm2->watchdog.reset_addr = md->base_address + (2 * md->register_stride);

    r = hm2_register_tram_read_region(hm2, hm2->watchdog.status_addr, (hm2->watchdog.num_instances * sizeof(u32)), &hm2->watchdog.status_reg);
    if (r < 0) {
        HM2_ERR("error registering tram read region for watchdog (%d)\n", r);
        goto fail0;
    }

    r = hm2_register_tram_write_region(hm2, hm2->watchdog.reset_addr, sizeof(u32), &hm2->watchdog.reset_reg);
    if (r < 0) {
        HM2_ERR("error registering tram write region for watchdog (%d)!\n", r);
        goto fail0;
    }

    // 
    // allocate memory for register buffers
    //

    hm2->watchdog.timer_reg = (u32 *)kmalloc(hm2->watchdog.num_instances * sizeof(u32), GFP_KERNEL);
    if (hm2->watchdog.timer_reg == NULL) {
        HM2_ERR("out of memory!\n");
        r = -ENOMEM;
        goto fail0;
    }


    //
    // export to HAL
    //

    // pins
    r = hal_pin_bit_newf(
        HAL_IO,
        &(hm2->watchdog.instance[0].hal.pin.has_bit),
        hm2->llio->comp_id,
        "%s.watchdog.has_bit",
        hm2->llio->name
    );
    if (r < 0) {
        HM2_ERR("error adding pin, aborting\n");
        r = -EINVAL;
        goto fail1;
    }

    // params
    r = hal_param_u32_newf(
        HAL_RW,
        &(hm2->watchdog.instance[0].hal.param.timeout_ns),
        hm2->llio->comp_id,
        "%s.watchdog.timeout_ns",
        hm2->llio->name
    );
    if (r < 0) {
        HM2_ERR("error adding param, aborting\n");
        r = -EINVAL;
        goto fail1;
    }


    // the function
    {
	hal_export_xfunct_args_t xfunct_args = {
	    .type = FS_XTHREADFUNC,
	    .funct.x = hm2_pet_watchdog,
	    .arg = hm2,
	    .uses_fp = 0,
	    .reentrant = 0,
	    .owner_id = hm2->llio->comp_id
	};

	if ((r = hal_export_xfunctf(&xfunct_args,
				    "%s.pet_watchdog",
				    hm2->llio->name)) != 0) {
	    HM2_ERR("hal_export pet_watchdog failed - %d\n", r);
	    r = -EINVAL;
            goto fail1;
	}
    }


    //
    // initialize the watchdog
    //

    *hm2->watchdog.instance[0].hal.pin.has_bit = 0;
    hm2->watchdog.instance[0].hal.param.timeout_ns = 5 * 1000 * 1000;  // default timeout is 5 milliseconds
    hm2->watchdog.instance[0].enable = 0;  // the first pet_watchdog will turn it on

    return hm2->watchdog.num_instances;

fail1:
    kfree(hm2->watchdog.timer_reg);

fail0:
    hm2->watchdog.num_instances = 0;
    return r;
}


void hm2_watchdog_print_module(hostmot2_t *hm2) {
    int i;
    HM2_PRINT("Watchdog: %d\n", hm2->watchdog.num_instances);
    if (hm2->watchdog.num_instances <= 0) return;
    HM2_PRINT("    clock_frequency: %d Hz (%s MHz)\n", hm2->watchdog.clock_frequency, hm2_hz_to_mhz(hm2->watchdog.clock_frequency));
    HM2_PRINT("    version: %d\n", hm2->watchdog.version);
    HM2_PRINT("    timer_addr: 0x%04X\n", hm2->watchdog.timer_addr);
    HM2_PRINT("    status_addr: 0x%04X\n", hm2->watchdog.status_addr);
    HM2_PRINT("    reset_addr: 0x%04X\n", hm2->watchdog.reset_addr);
    for (i = 0; i < hm2->watchdog.num_instances; i ++) {
        HM2_PRINT("    instance %d:\n", i);
        HM2_PRINT("        param timeout_ns = %u\n", hm2->watchdog.instance[i].hal.param.timeout_ns);
        HM2_PRINT("        pin has_bit = %d\n", (*hm2->watchdog.instance[i].hal.pin.has_bit));
        HM2_PRINT("        reg timer = 0x%08X\n", hm2->watchdog.timer_reg[i]);
    }
}
Esempio n. 14
0
void hm2_pwmgen_print_module(hostmot2_t *hm2) {
    int i;
    HM2_PRINT("PWMGen: %d\n", hm2->pwmgen.num_instances);
    if (hm2->pwmgen.num_instances <= 0) return;
    HM2_PRINT("    clock_frequency: %d Hz (%s MHz)\n", hm2->pwmgen.clock_frequency, hm2_hz_to_mhz(hm2->pwmgen.clock_frequency));
    HM2_PRINT("    version: %d\n", hm2->pwmgen.version);
    HM2_PRINT("    pwmgen_master_rate_dds: 0x%08X (%d)\n", hm2->pwmgen.pwmgen_master_rate_dds_reg, hm2->pwmgen.pwmgen_master_rate_dds_reg);
    HM2_PRINT("    pdmgen_master_rate_dds: 0x%08X (%d)\n", hm2->pwmgen.pdmgen_master_rate_dds_reg, hm2->pwmgen.pdmgen_master_rate_dds_reg);
    HM2_PRINT("    enable: 0x%08X\n", hm2->pwmgen.enable_reg);
    HM2_PRINT("    pwm_value_addr: 0x%04X\n", hm2->pwmgen.pwm_value_addr);
    HM2_PRINT("    pwm_mode_addr: 0x%04X\n", hm2->pwmgen.pwm_mode_addr);
    HM2_PRINT("    pwmgen_master_rate_dds_addr: 0x%04X\n", hm2->pwmgen.pwmgen_master_rate_dds_addr);
    HM2_PRINT("    pdmgen_master_rate_dds_addr: 0x%04X\n", hm2->pwmgen.pdmgen_master_rate_dds_addr);
    HM2_PRINT("    enable_addr: 0x%04X\n", hm2->pwmgen.enable_addr);
    for (i = 0; i < hm2->pwmgen.num_instances; i ++) {
        HM2_PRINT("    instance %d:\n", i);
        HM2_PRINT("        hw:\n");
        HM2_PRINT(
            "            pwm_val = 0x%08X (%s%d)\n",
            hm2->pwmgen.pwm_value_reg[i],
            ((hm2->pwmgen.pwm_value_reg[i] & 0x80000000) ? "-" : ""),
            ((hm2->pwmgen.pwm_value_reg[i]>>16) & 0x7fff)
        );
        HM2_PRINT("            pwm_mode = 0x%08X\n", hm2->pwmgen.pwm_mode_reg[i]);
    }
}
Esempio n. 15
0
int hm2_uart_parse_md(hostmot2_t *hm2, int md_index) 
{
    // All this function actually does is allocate memory
    // and give the uart modules names. 
    
    
    // 
    // some standard sanity checks
    //
    
    int i, r = -EINVAL;
    hm2_module_descriptor_t *md = &hm2->md[md_index];
    static int last_gtag = -1;
    
    //The UART declares a TX and RX module separately
    
    if (!hm2_md_is_consistent_or_complain(hm2, md_index, 0, 4, 0x10, 0x000F)) {
        HM2_ERR("inconsistent Module Descriptor!\n");
        return -EINVAL;
    }
    
    if (hm2->uart.num_instances > 1 && last_gtag == md->gtag) {
        HM2_ERR(
                "found duplicate Module Descriptor for %s (inconsistent "
                "firmware), not loading driver %i %i\n",
                hm2_get_general_function_name(md->gtag), md->gtag, last_gtag
                );
        return -EINVAL;
    }
    last_gtag = md->gtag;
    
    if (hm2->config.num_uarts > md->instances) {
        HM2_ERR(
                "config defines %d uarts, but only %d are available, "
                "not loading driver\n",
                hm2->config.num_uarts,
                md->instances
                );
        return -EINVAL;
    }
    
    if (hm2->config.num_uarts == 0) {
        return 0;
    }
    
    // 
    // looks good, start, or continue, initializing
    // 
    
    if (hm2->uart.num_instances == 0){
        if (hm2->config.num_uarts == -1) {
            hm2->uart.num_instances = md->instances;
        } else {
            hm2->uart.num_instances = hm2->config.num_uarts;
        }
        
        hm2->uart.instance = (hm2_uart_instance_t *)hal_malloc(hm2->uart.num_instances 
                                                               * sizeof(hm2_uart_instance_t));
        if (hm2->uart.instance == NULL) {
            HM2_ERR("out of memory!\n");
            r = -ENOMEM;
            goto fail0;
        }
    }
    
    for (i = 0 ; i < hm2->uart.num_instances ; i++){
        hm2_uart_instance_t *inst = &hm2->uart.instance[i];
        // For the time being we assume that all UARTS come on pairs
        if (inst->clock_freq == 0){
            inst->clock_freq = md->clock_freq;
            r = sprintf(inst->name, "%s.uart.%01d", hm2->llio->name, i);
            HM2_PRINT("created UART Interface function %s.\n", inst->name);
        }
        if (md->gtag == HM2_GTAG_UART_TX){
            inst->tx1_addr = md->base_address + i * md->instance_stride;
            inst->tx2_addr = md->base_address + i * md->instance_stride + 0x4;
            inst->tx3_addr = md->base_address + i * md->instance_stride + 0x8;
            inst->tx4_addr = md->base_address + i * md->instance_stride + 0xC;
            inst->tx_fifo_count_addr = (md->base_address 
                                        + md->register_stride 
                                        + i * md->instance_stride);
            inst->tx_bitrate_addr = (md->base_address 
                                     + 2 * md->register_stride
                                     + i * md->instance_stride);
            inst->tx_mode_addr = (md->base_address 
                                  + 3 * md->register_stride
                                  +i * md->instance_stride);  
        }
        else if (md->gtag == HM2_GTAG_UART_RX){
            inst->rx1_addr = md->base_address + i * md->instance_stride;
            inst->rx2_addr = md->base_address + i * md->instance_stride + 0x4;
            inst->rx3_addr = md->base_address + i * md->instance_stride + 0x8;
            inst->rx4_addr = md->base_address + i * md->instance_stride + 0xC;
            inst->rx_fifo_count_addr = (md->base_address 
                                        + md->register_stride 
                                        + i * md->instance_stride);
            inst->rx_bitrate_addr = (md->base_address 
                                     + 2 * md->register_stride
                                     + i * md->instance_stride);
            inst->rx_mode_addr = (md->base_address 
                                  + 3 * md->register_stride 
                                  +i * md->instance_stride);    
        }
        else{
            HM2_ERR("Something very wierd happened");
            goto fail0;
        }
        
    }
    return hm2->uart.num_instances;
fail0:
    return r;
}
int hm2_watchdog_parse_md(hostmot2_t *hm2, int md_index) {
    hm2_module_descriptor_t *md = &hm2->md[md_index];
    int r;


    // 
    // some standard sanity checks
    //

    if (!hm2_md_is_consistent_or_complain(hm2, md_index, 0, 3, 4, 0)) {
        HM2_ERR("inconsistent Module Descriptor!\n");
        return -EINVAL;
    }

    if (hm2->watchdog.num_instances != 0) {
        HM2_ERR(
            "found duplicate Module Descriptor for %s (inconsistent firmware), not loading driver\n",
            hm2_get_general_function_name(md->gtag)
        );
        return -EINVAL;
    }


    // 
    // special sanity checks for watchdog
    //

    if (md->instances != 1) {
        HM2_PRINT("MD declares %d watchdogs!  only using the first one...\n", md->instances);
    }


    // 
    // looks good, start initializing
    // 


    hm2->watchdog.num_instances = 1;

    hm2->watchdog.instance = (hm2_watchdog_instance_t *)hal_malloc(hm2->watchdog.num_instances * sizeof(hm2_watchdog_instance_t));
    if (hm2->watchdog.instance == NULL) {
        HM2_ERR("out of memory!\n");
        r = -ENOMEM;
        goto fail0;
    }

    hm2->watchdog.clock_frequency = md->clock_freq;
    hm2->watchdog.version = md->version;

    hm2->watchdog.timer_addr = md->base_address + (0 * md->register_stride);
    hm2->watchdog.status_addr = md->base_address + (1 * md->register_stride);
    hm2->watchdog.reset_addr = md->base_address + (2 * md->register_stride);


    // 
    // allocate memory for register buffers
    //

    hm2->watchdog.status_reg = (u32 *)kmalloc(hm2->watchdog.num_instances * sizeof(u32), GFP_KERNEL);
    if (hm2->watchdog.status_reg == NULL) {
        HM2_ERR("out of memory!\n");
        r = -ENOMEM;
        goto fail0;
    }

    hm2->watchdog.reset_reg = (u32 *)kmalloc(hm2->watchdog.num_instances * sizeof(u32), GFP_KERNEL);
    if (hm2->watchdog.reset_reg == NULL) {
        HM2_ERR("out of memory!\n");
        r = -ENOMEM;
        goto fail1;
    }

    hm2->watchdog.timer_reg = (u32 *)kmalloc(hm2->watchdog.num_instances * sizeof(u32), GFP_KERNEL);
    if (hm2->watchdog.timer_reg == NULL) {
        HM2_ERR("out of memory!\n");
        r = -ENOMEM;
        goto fail2;
    }


    //
    // export to HAL
    //

    // pins
    r = hal_pin_bit_newf(
        HAL_IO,
        &(hm2->watchdog.instance[0].hal.pin.has_bit),
        hm2->llio->comp_id,
        "%s.watchdog.has_bit",
        hm2->llio->name
    );
    if (r < 0) {
        HM2_ERR("error adding pin, aborting\n");
        r = -EINVAL;
        goto fail3;
    }

    // params
    r = hal_param_u32_newf(
        HAL_RW,
        &(hm2->watchdog.instance[0].hal.param.timeout_ns),
        hm2->llio->comp_id,
        "%s.watchdog.timeout_ns",
        hm2->llio->name
    );
    if (r < 0) {
        HM2_ERR("error adding param, aborting\n");
        r = -EINVAL;
        goto fail3;
    }


    // the function
    {
        char name[HAL_NAME_LEN + 1];

        rtapi_snprintf(name, sizeof(name), "%s.pet_watchdog", hm2->llio->name);
        r = hal_export_funct(name, hm2_pet_watchdog, hm2, 0, 0, hm2->llio->comp_id);
        if (r != 0) {
            HM2_ERR("error %d exporting pet_watchdog function %s\n", r, name);
            r = -EINVAL;
            goto fail3;
        }
    }


    //
    // initialize the watchdog
    //

    *hm2->watchdog.instance[0].hal.pin.has_bit = 0;
    hm2->watchdog.instance[0].hal.param.timeout_ns = 5 * 1000 * 1000;  // default timeout is 5 milliseconds
    hm2->watchdog.instance[0].enable = 0;  // the first pet_watchdog will turn it on

    hm2->watchdog.instance[0].warned_about_short_timeout = 0;

    hm2->watchdog.reset_reg[0] = 0x5a000000;
    hm2->watchdog.status_reg[0] = 0;


    return hm2->watchdog.num_instances;


fail3:
    kfree(hm2->watchdog.timer_reg);

fail2:
    kfree(hm2->watchdog.reset_reg);

fail1:
    kfree(hm2->watchdog.status_reg);

fail0:
    hm2->watchdog.num_instances = 0;
    return r;
}