ioport.c

来自「CNC 的开放码,EMC2 V2.2.8版」· C语言 代码 · 共 605 行 · 第 1/2 页

C
605
字号
        // it's a full GPIO        //        if (hm2->pin[i].gtag == HM2_GTAG_IOPORT) {            r = hal_pin_bit_newf(                HAL_IN,                &(hm2->pin[i].instance->hal.pin.out),                hm2->llio->comp_id,                "%s.gpio.%s.%03d.out",                hm2->llio->name,                hm2->llio->ioport_connector_name[port],                i            );            if (r != HAL_SUCCESS) {                ERR("error %d adding gpio pin, aborting\n", r);                return -EINVAL;            }            *(hm2->pin[i].instance->hal.pin.out) = 0;            // parameters            r = hal_param_bit_newf(                HAL_RW,                &(hm2->pin[i].instance->hal.param.is_output),                hm2->llio->comp_id,                "%s.gpio.%s.%03d.is_output",                hm2->llio->name,                hm2->llio->ioport_connector_name[port],                i            );            if (r != HAL_SUCCESS) {                ERR("error %d adding gpio param, aborting\n", r);                return -EINVAL;            }            hm2->pin[i].instance->hal.param.is_output = 0;        }    }    return 0;}void hm2_ioport_print_module(hostmot2_t *hm2) {    int i;    PRINT("IO Ports: %d\n", hm2->ioport.num_instances);    if (hm2->ioport.num_instances <= 0) return;    PRINT("    clock_frequency: %d Hz (%s MHz)\n", hm2->ioport.clock_frequency, hm2_hz_to_mhz(hm2->ioport.clock_frequency));    PRINT("    version: %d\n", hm2->ioport.version);    PRINT("    data_addr: 0x%04X\n", hm2->ioport.data_addr);    PRINT("    ddr_addr: 0x%04X\n", hm2->ioport.ddr_addr);    PRINT("    alt_source_addr: 0x%04X\n", hm2->ioport.alt_source_addr);    PRINT("    open_drain_addr: 0x%04X\n", hm2->ioport.open_drain_addr);    PRINT("    output_invert_addr: 0x%04X\n", hm2->ioport.output_invert_addr);    for (i = 0; i < hm2->ioport.num_instances; i ++) {        PRINT("    instance %d:\n", i);        PRINT("        data_read = 0x%06X\n", hm2->ioport.data_read_reg[i]);        PRINT("        data_write = 0x%06X\n", hm2->ioport.data_write_reg[i]);        PRINT("        ddr = 0x%06X\n", hm2->ioport.ddr_reg[i]);        PRINT("        alt_source = 0x%06X\n", hm2->ioport.alt_source_reg[i]);        PRINT("        open_drain = 0x%06X\n", hm2->ioport.open_drain_reg[i]);        PRINT("        output_invert = 0x%06X\n", hm2->ioport.output_invert_reg[i]);    }}static void hm2_ioport_force_write_ddr(hostmot2_t *hm2) {    int size = hm2->ioport.num_instances * sizeof(u32);    hm2->llio->write(hm2->llio, hm2->ioport.ddr_addr, hm2->ioport.ddr_reg, size);    memcpy(hm2->ioport.written_ddr, hm2->ioport.ddr_reg, size);}static void hm2_ioport_force_write_output_invert(hostmot2_t *hm2) {    int size = hm2->ioport.num_instances * sizeof(u32);    hm2->llio->write(hm2->llio, hm2->ioport.output_invert_addr, hm2->ioport.output_invert_reg, size);    memcpy(hm2->ioport.written_output_invert, hm2->ioport.output_invert_reg, size);}static void hm2_ioport_force_write_open_drain(hostmot2_t *hm2) {    int size = hm2->ioport.num_instances * sizeof(u32);    hm2->llio->write(hm2->llio, hm2->ioport.open_drain_addr, hm2->ioport.open_drain_reg, size);    memcpy(hm2->ioport.written_open_drain, hm2->ioport.open_drain_reg, size);}void hm2_ioport_update(hostmot2_t *hm2) {    int port;    int port_pin;    for (port = 0; port < hm2->ioport.num_instances; port ++) {        for (port_pin = 0; port_pin < hm2->idrom.port_width; port_pin ++) {            int io_pin = (port * hm2->idrom.port_width) + port_pin;            if (hm2->pin[io_pin].gtag == HM2_GTAG_IOPORT) {                if (hm2->pin[io_pin].instance->hal.param.is_output) {                    hm2->pin[io_pin].direction = HM2_PIN_DIR_IS_OUTPUT;                } else {                    hm2->pin[io_pin].direction = HM2_PIN_DIR_IS_INPUT;                }            }            if (hm2->pin[io_pin].direction == HM2_PIN_DIR_IS_OUTPUT) {                hm2->ioport.ddr_reg[port] |= (1 << port_pin);  // set the bit in the ddr register                // Open Drain Register                if (hm2->pin[io_pin].instance->hal.param.is_opendrain) {                    hm2->ioport.open_drain_reg[port] |= (1 << port_pin);  // set the bit in the open drain register                } else {                    hm2->ioport.open_drain_reg[port] &= ~(1 << port_pin);  // clear the bit in the open drain register                }                // Invert Output Register                if (hm2->pin[io_pin].instance->hal.param.invert_output) {                    hm2->ioport.output_invert_reg[port] |= (1 << port_pin);  // set the bit in the output invert register                } else {                    hm2->ioport.output_invert_reg[port] &= ~(1 << port_pin);  // clear the bit in the output invert register                }            } else {                hm2->ioport.open_drain_reg[port] &= ~(1 << port_pin);  // clear the bit in the open drain register                hm2->ioport.ddr_reg[port] &= ~(1 << port_pin);  // clear the bit in the ddr register                // it doesnt matter what the Invert Output register says            }        }    }}void hm2_ioport_force_write(hostmot2_t *hm2) {    int size = hm2->ioport.num_instances * sizeof(u32);    hm2_ioport_update(hm2);    hm2_ioport_force_write_ddr(hm2);    hm2_ioport_force_write_output_invert(hm2);    hm2_ioport_force_write_open_drain(hm2);    hm2->llio->write(hm2->llio, hm2->ioport.alt_source_addr,    hm2->ioport.alt_source_reg,    size);}void hm2_ioport_write(hostmot2_t *hm2) {    int port;    hm2_ioport_update(hm2);    for (port = 0; port < hm2->ioport.num_instances; port ++) {        if (hm2->ioport.written_ddr[port] != hm2->ioport.ddr_reg[port]) {            hm2_ioport_force_write_ddr(hm2);            break;        }    }    for (port = 0; port < hm2->ioport.num_instances; port ++) {        if (hm2->ioport.written_open_drain[port] != hm2->ioport.open_drain_reg[port]) {            hm2_ioport_force_write_open_drain(hm2);            break;        }    }    for (port = 0; port < hm2->ioport.num_instances; port ++) {        if (hm2->ioport.written_output_invert[port] != hm2->ioport.output_invert_reg[port]) {            hm2_ioport_force_write_output_invert(hm2);            break;        }    }}//// initialize the tram write registers//void hm2_ioport_gpio_tram_write_init(hostmot2_t *hm2) {    int port;    for (port = 0; port < hm2->ioport.num_instances; port ++) {        hm2->ioport.data_write_reg[port] = 0;    }}//// the ioport.data_read buffer has been updated by a TRAM read from the values in the ioport data register// this function sets the HAL pins based on the values in the data_read register buffer//void hm2_ioport_gpio_process_tram_read(hostmot2_t *hm2) {    int port;    int port_pin;    //     // parse it out to the HAL pins    //    for (port = 0; port < hm2->ioport.num_instances; port ++) {        for (port_pin = 0; port_pin < hm2->idrom.port_width; port_pin ++) {            int io_pin = (port * hm2->idrom.port_width) + port_pin;            hal_bit_t bit;            if (hm2->pin[io_pin].direction != HM2_PIN_DIR_IS_INPUT) continue;            bit = (hm2->ioport.data_read_reg[port] >> port_pin) & 0x1;            *hm2->pin[io_pin].instance->hal.pin.in = bit;            *hm2->pin[io_pin].instance->hal.pin.in_not = !bit;        }    }}//// this function sets the data_write register TRAM buffer from the values of the HAL pins// the data_write buffer will get written to the TRAM and thus to the ioport data register by the caller// void hm2_ioport_gpio_prepare_tram_write(hostmot2_t *hm2) {    int port;    int port_pin;    //    // copy HAL pins to HM2 pins    //    for (port = 0; port < hm2->ioport.num_instances; port ++) {        for (port_pin = 0; port_pin < hm2->idrom.port_width; port_pin ++) {            int io_pin = (port * hm2->idrom.port_width) + port_pin;            if (hm2->pin[io_pin].gtag != HM2_GTAG_IOPORT) continue;            hm2->ioport.data_write_reg[port] &= ~(1 << port_pin);   // zero the bit            hm2->ioport.data_write_reg[port] |= (*(hm2->pin[io_pin].instance->hal.pin.out) << port_pin);  // and set it as appropriate        }    }}void hm2_ioport_gpio_read(hostmot2_t *hm2) {    int port;    int port_pin;    hm2->llio->read(        hm2->llio,        hm2->ioport.data_addr,        hm2->ioport.data_read_reg,        hm2->ioport.num_instances * sizeof(u32)    );    // FIXME: this block duplicates code in hm2_ioport_gpio_process_tram_read()    for (port = 0; port < hm2->ioport.num_instances; port ++) {        for (port_pin = 0; port_pin < hm2->idrom.port_width; port_pin ++) {            int io_pin = (port * hm2->idrom.port_width) + port_pin;            hal_bit_t bit;            if (hm2->pin[io_pin].direction != HM2_PIN_DIR_IS_INPUT) continue;            bit = (hm2->ioport.data_read_reg[port] >> port_pin) & 0x1;            *hm2->pin[io_pin].instance->hal.pin.in = bit;            *hm2->pin[io_pin].instance->hal.pin.in_not = !bit;        }    }}void hm2_ioport_gpio_write(hostmot2_t *hm2) {    int port;    int port_pin;    hm2_ioport_write(hm2);  // this updates any config registers that need it    // FIXME: this block duplicates code in hm2_ioport_gpio_prepare_tram_write()    for (port = 0; port < hm2->ioport.num_instances; port ++) {        for (port_pin = 0; port_pin < hm2->idrom.port_width; port_pin ++) {            int io_pin = (port * hm2->idrom.port_width) + port_pin;            if (hm2->pin[io_pin].gtag != HM2_GTAG_IOPORT) continue;            hm2->ioport.data_write_reg[port] &= ~(1 << port_pin);   // zero the bit            hm2->ioport.data_write_reg[port] |= (*(hm2->pin[io_pin].instance->hal.pin.out) << port_pin);  // and set it as appropriate        }    }    hm2->llio->write(        hm2->llio,        hm2->ioport.data_addr,        hm2->ioport.data_write_reg,        hm2->ioport.num_instances * sizeof(u32)    );}

⌨️ 快捷键说明

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