#include #include #include "ktiva.h" #include "ksync.h" ///////////////////////////////////////////////////////////////////////////// extern int g_sw; ///////////////////////////////////////////////////////////////////////////// static const long g_kty_tab[][2] = { {199, 1250}, {351, 1000}, {643, 750}, {1185, 500}, {2048, 250}, {3025, 0}, {3705, -250} }; #define KTY_TAB_LEN _countof(g_kty_tab) ///////////////////////////////////////////////////////////////////////////// static int _lin_kty(int resistance) { int i; if(resistance <= g_kty_tab[0][0]) return(g_kty_tab[0][1]); else if(resistance >= g_kty_tab[KTY_TAB_LEN - 1][0]) return(g_kty_tab[KTY_TAB_LEN - 1][1]); for(i = 1; i < KTY_TAB_LEN; i++) { if(g_kty_tab[i][0] >= resistance) break; } // linear interpolation return g_kty_tab[i - 1][1] + // y1 + ( // ( (g_kty_tab[i][1] - g_kty_tab[i - 1][1]) * // (y2 - y1) * (resistance - g_kty_tab[i - 1][0]) / // (x - x1) / (g_kty_tab[i][0] - g_kty_tab[i - 1][0]) // (x2 - x1) ); // ) } ///////////////////////////////////////////////////////////////////////////// static int _scale (int in_min, int in_max, int out_min, int out_max, int wert) { int abc; abc = (((long)out_max - (long)out_min) * (long)wert) / ( (long)in_max - (long)in_min); abc = abc + out_min; return abc; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// int ktiva_wait_ack(struct file *pf) { int ret, i = 0; unsigned char c = 0; #if _SITARA_EGGELSBERG unsigned long start = jiffies; unsigned long timeout = jiffies + 4; #else // _SITARA_EGGELSBERG unsigned long timeout = jiffies + 2 *HZ; // 2 sec. timeout #endif // _SITARA_EGGELSBERG while(c != CMD_ACK) { ++i; ksync_sleep_jiffies(1); if((ret = kspi_rx_byte(pf, &c)) < 0) return ret; else if(c == CMD_NAK) { KALERT("%s: received NAK!\n", __FUNCTION__); return -ECOMM; } else if(c != CMD_ACK) { if(time_is_before_eq_jiffies(timeout)) { KALERT("%s: timeout!\n", __FUNCTION__); return -ETIME; } } } #if _SITARA_EGGELSBERG KALERT("ktiva_wait_ack: jiffies: %lu, loops: %d\n", ((long)jiffies - (long)start), i); #endif // _SITARA_EGGELSBERG return (c == CMD_ACK) ? 0 : -1; } ///////////////////////////////////////////////////////////////////////////// int ktiva_send_frame(struct file *pf, unsigned char cmd, const void *pData, size_t nCbData) { int ret; size_t i, j = 0; unsigned char buf[KTIVA_MAX_BUFFER_SIZE]; const unsigned char *pdat = (const unsigned char*)pData; #if _EXTENDED_ERROR_CHECK if(nCbData > (sizeof(buf) - 3)) { KALERT("%s: Invalid data length: %zu!\n", __FUNCTION__, nCbData); return -ENOMEM; } else if(nCbData && !pData) { KALERT("%s: Invalid data pointer!\n", __FUNCTION__); return -EINVAL; } #endif // _EXTENDED_ERROR_CHECK buf[0] = (unsigned char)nCbData + 3; buf[1] = cmd; // init checksum buf[2] = cmd; for(i = 0, j = 3; i < nCbData; ++i, ++j) { buf[1] += pdat[i]; // calc checksum buf[j] = pdat[i]; // fill in data } if((ret = kspi_tx(pf, buf, j)) < 0) // send data frame return ret; if((ret = ktiva_wait_ack(pf)) == 0) // wait for ACK ret = (int)nCbData; return ret; } ///////////////////////////////////////////////////////////////////////////// int ktiva_recv_frame(struct file *pf, unsigned char cmd, void *pData, size_t nCbData) { int ret, i; unsigned char chk = 0, len = 0; unsigned char buf[KTIVA_MAX_BUFFER_SIZE]; // unsigned long start = jiffies; unsigned long timeout = jiffies + HZ; // 1 sec. timeout #if _EXTENDED_ERROR_CHECK if(nCbData && !pData) { KALERT("%s: Invalid data pointer!\n", __FUNCTION__); return -EINVAL; } #endif // _EXTENDED_ERROR_CHECK do { if((ret = kspi_rx_byte(pf, &len)) < 0) // receive length byte return ret; if(!len) { ksync_sleep_jiffies(1); if(time_is_before_eq_jiffies(timeout)) { KALERT("%s: timeout!\n", __FUNCTION__); return -ETIME; } } } while(!len); if(len > (int)(nCbData + 3)) { KALERT("%s: Insufficient buffer length: %zu - need %hhu!\n", __FUNCTION__, nCbData, len - 3); return -ENOMEM; } else if(len < 2) { KALERT("%s: received invalid lenght: %hhu!\n", __FUNCTION__, len); return -EPROTO; } if((ret = kspi_rx(pf, buf, len - 1)) < 0) // receive checksum, cmd + data return ret; else if(ret != (len - 1)) { KALERT("%s: kspi_rx returned invalid lenght: %d!\n", __FUNCTION__, ret); return -EPROTO; } else if(buf[1] != cmd) { KALERT("%s: invalid command: %02hhX!\n", __FUNCTION__, buf[1]); return -EPROTO; } // KALERT("ktiva_recv_frame: ordered: %hhu, received: %d!\n", len - 1, ret); for(i = 1; i < ret; ++i) { chk += buf[i]; // calc checksum } if(buf[0] != chk) { KALERT("%s: checksum err: [l=%hhu, c=0x%02hhX], recv: 0x%02hhX, calc: 0x%02hhX!\n", __FUNCTION__, len, buf[1], buf[0], chk); #if 1 for(i = 2; i < ret; ++i) KALERT("%02hhX ", buf[i]); KALERT("\n"); #endif // _SITARA_EGGELSBERG return -EPROTO; } if(nCbData) memcpy(pData, &buf[2], ret - 2); // KALERT("%s: jiffies: %lu\n", __FUNCTION__, ((long)jiffies - (long)start)); return ret - 2; } ///////////////////////////////////////////////////////////////////////////// int ktiva_recv_bootloader_frame(struct file *pf, unsigned char cmd, void *pData, size_t nCbData) { int ret, i; unsigned char chk = 0, len = 0; unsigned char buf[KTIVA_MAX_BUFFER_SIZE]; // unsigned long start = jiffies; unsigned long timeout = jiffies + HZ; // 1 sec. timeout #if _EXTENDED_ERROR_CHECK if(nCbData && !pData) { KALERT("%s: Invalid data pointer!\n", __FUNCTION__); return -EINVAL; } #endif // _EXTENDED_ERROR_CHECK do { if((ret = kspi_rx_byte(pf, &len)) < 0) // receive length byte return ret; if(!len) { ksync_sleep_jiffies(1); if(time_is_before_eq_jiffies(timeout)) { KALERT("%s: timeout!\n", __FUNCTION__); return -ETIME; } } } while(!len); if(len > (int)(nCbData + 2)) { KALERT("%s: Insufficient buffer length: %zu - need %hhu!\n", __FUNCTION__, nCbData, len - 3); return -ENOMEM; } else if(len < 2) { KALERT("%s: received invalid lenght: %hhu!\n", __FUNCTION__, len); return -EPROTO; } if((ret = kspi_rx(pf, buf, len - 1)) < 0) // receive checksum + data return ret; else if(ret != (len - 1)) { KALERT("%s: kspi_rx returned invalid lenght: %d!\n", __FUNCTION__, ret); return -EPROTO; } for(i = 1; i < ret; ++i) { chk += buf[i]; // calc checksum } if(buf[0] != chk) { KALERT("%s: checksum error: recv: 0x%02hhX, calc: 0x%02hhX!\n", __FUNCTION__, buf[0], chk); return -EPROTO; } if(nCbData) memcpy(pData, &buf[1], ret - 1); return ret - 1; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// int TivaRevive(struct file *pf) { int ret, i = 0; unsigned char c = 0; for(i = 0; i < 256; ++i) { if((ret = kspi_rx_byte(pf, &c)) < 0) { KALERT("%s - kspi_rx_byte failed: %d\n", __FUNCTION__, ret); return ret; } else if(c == CMD_ACK) break; else if(c == CMD_NAK) { KALERT("%s: received NAK\n", __FUNCTION__); break; } if(i && !(i % 8)) { ksync_sleep_jiffies(1); } } if(i == 256) { if((ret = kspi_tx_byte(pf, CMD_ACK)) < 0) { KALERT("%s - kspi_tx_byte failed: %d\n", __FUNCTION__, ret); return ret; } } KALERT("%s: loops: %d\n\n", __FUNCTION__, i); return (c == CMD_ACK) ? 0 : -1; } ///////////////////////////////////////////////////////////////////////////// int TivaCmdGetFirmwareVersion(struct file *pf, int *Hw, int *Sw) { int ret; if((ret = ktiva_send_frame(pf, COMMAND_GET_HWSW_REV, NULL, 0)) == 0) { int data[2]; if((ret = ktiva_recv_frame(pf, COMMAND_GET_HWSW_REV, data, sizeof(data))) == sizeof(data)) { if(Hw) *Hw = ntohl(data[0]); if(Sw) *Sw = ntohl(data[1]); kspi_tx_byte(pf, CMD_ACK); ret = 0; } else { KALERT("%s - ktiva_recv_frame failed: %d\n", __FUNCTION__, ret); } } else { KALERT("%s - ktiva_send_frame failed: %d!\n", __FUNCTION__, ret); } return ret; } ///////////////////////////////////////////////////////////////////////////// int TivaCmdGetADC(struct file *pf, LPTIVA_ADC padc) { int ret; #if _EXTENDED_ERROR_CHECK if(!padc) { KALERT("%s: Invalid struct pointer!\n", __FUNCTION__); return -EINVAL; } #endif // _EXTENDED_ERROR_CHECK if((ret = ktiva_send_frame(pf, COMMAND_GET_ADC, NULL, 0)) == 0) { unsigned short data[6]; if((ret = ktiva_recv_frame(pf, COMMAND_GET_ADC, data, sizeof(data))) == sizeof(data)) { padc->UVers = _scale(0, 4096, 0, 4375, ntohs(data[0])); // val / 100.0 + 0.4 (Versorgungsspannung skaliert) padc->UBatV3 = _scale(0, 4096, 0, 500, ntohs(data[1])); // val / 100.0 (Spannung Pufferbatterie skaliert) padc->Temp = _lin_kty(ntohs(data[2])); // val / 10.0 (Boardtemperatur linear interpoliert) padc->UV5Vsys = _scale(0, 4096, 0, 570, ntohs(data[3])); // val / 100.0 (interne 5V Hauptversorgungsspannung skaliert) padc->UV3V6Bat = _scale(0, 4096, 0, 500, ntohs(data[4])); // val / 100.0 (interne 3V Akkuspannung skaliert) padc->TempTIVA = ntohs(data[5]); // 147.5 - 187.5 * val / 4096.0 (TIVA-Temperatur) kspi_tx_byte(pf, CMD_ACK); ret = 0; } else { KALERT("%s - ktiva_recv_frame failed: %d\n", __FUNCTION__, ret); } } else { KALERT("%s - ktiva_send_frame failed: %d!\n", __FUNCTION__, ret); } return ret; } ///////////////////////////////////////////////////////////////////////////// int TivaCmdGetUptime(struct file *pf, unsigned long long *put) { int ret; if(g_sw < 0x113) { #if _SUPPORT_LEGACY_UPTIME unsigned int ut; if((ret = TivaCmdGetAddress(pf, KTIVA_UPTIME_ADDRESS, &ut)) == 0) *put = ut; return ret; #else // _SUPPORT_LEGACY_UPTIME return -EPERM; #endif // _SUPPORT_LEGACY_UPTIME } #if _EXTENDED_ERROR_CHECK if(!put) { KALERT("%s: Invalid data pointer!\n", __FUNCTION__); return -EINVAL; } #endif // _EXTENDED_ERROR_CHECK if((ret = ktiva_send_frame(pf, COMMAND_GET_UPTIME, NULL, 0)) == 0) { unsigned long long data; if((ret = ktiva_recv_frame(pf, COMMAND_GET_UPTIME, &data, sizeof(data))) == sizeof(data)) { *put = be64_to_cpu(data); kspi_tx_byte(pf, CMD_ACK); ret = 0; } else { KALERT("%s - ktiva_recv_frame failed: %d\n", __FUNCTION__, ret); } } else { KALERT("%s - ktiva_send_frame failed: %d!\n", __FUNCTION__, ret); } return ret; } ///////////////////////////////////////////////////////////////////////////// int TivaCmdGetAddress(struct file *pf, unsigned int addr, unsigned int *val) { int ret; unsigned int data = cpu_to_be32(addr); #if _EXTENDED_ERROR_CHECK if(!val) { KALERT("%s: Invalid data pointer!\n", __FUNCTION__); return -EINVAL; } #endif // _EXTENDED_ERROR_CHECK if((ret = ktiva_send_frame(pf, COMMAND_GET_ADDR, &data, sizeof(data))) == sizeof(data)) { if((ret = ktiva_recv_frame(pf, COMMAND_GET_ADDR, &data, sizeof(data))) == sizeof(data)) { *val = be32_to_cpu(data); kspi_tx_byte(pf, CMD_ACK); ret = 0; } else { KALERT("%s - ktiva_recv_frame failed: %d\n", __FUNCTION__, ret); if(ret > 0) ret = -1; } } else { KALERT("%s - ktiva_send_frame failed: %d!\n", __FUNCTION__, ret); } return ret; } ///////////////////////////////////////////////////////////////////////////// int TivaCmdPing(struct file *pf) { int ret; if((ret = ktiva_send_frame(pf, COMMAND_PING, NULL, 0)) != 0) { KALERT("%s - ktiva_send_frame failed: %d!\n", __FUNCTION__, ret); } return ret; } ///////////////////////////////////////////////////////////////////////////// int TivaCmdGetStatus(struct file *pf, unsigned char *stat) { int ret; unsigned char data; #if _EXTENDED_ERROR_CHECK if(!stat) { KALERT("%s: Invalid data pointer!\n", __FUNCTION__); return -EINVAL; } #endif // _EXTENDED_ERROR_CHECK if((ret = ktiva_send_frame(pf, COMMAND_GET_STATUS, NULL, 0)) == 0) { if((ret = ktiva_recv_frame(pf, COMMAND_GET_STATUS, &data, sizeof(data))) == sizeof(data)) { *stat = data; kspi_tx_byte(pf, CMD_ACK); ret = 0; } else { KALERT("%s - ktiva_recv_frame failed: %d\n", __FUNCTION__, ret); } } else { KALERT("%s - ktiva_send_frame failed: %d!\n", __FUNCTION__, ret); } return ret; } ///////////////////////////////////////////////////////////////////////////// int TivaCmdGetBootloaderStatus(struct file *pf, unsigned char *stat) { int ret; unsigned char data; #if _EXTENDED_ERROR_CHECK if(!stat) { KALERT("%s: Invalid data pointer!\n", __FUNCTION__); return -EINVAL; } #endif // _EXTENDED_ERROR_CHECK if((ret = ktiva_send_frame(pf, COMMAND_GET_STATUS, NULL, 0)) == 0) { if((ret = ktiva_recv_bootloader_frame(pf, COMMAND_GET_STATUS, &data, sizeof(data))) == sizeof(data)) { *stat = data; kspi_tx_byte(pf, CMD_ACK); ret = 0; } else { KALERT("%s - ktiva_recv_frame failed: %d\n", __FUNCTION__, ret); } } else { KALERT("%s - ktiva_send_frame failed: %d!\n", __FUNCTION__, ret); } return ret; } ///////////////////////////////////////////////////////////////////////////// int TivaCmdStartBootloader(struct file *pf) { int ret; if((ret = ktiva_send_frame(pf, COMMAND_START_BOOTLOADER, NULL, 0)) != 0) { KALERT("%s - ktiva_send_frame failed: %d!\n", __FUNCTION__, ret); } return ret; } ///////////////////////////////////////////////////////////////////////////// int TivaCmdStartDownload(struct file *pf, unsigned int addr, size_t size) { int ret; unsigned int data[2] = {cpu_to_be32(addr), cpu_to_be32((unsigned int)size)}; KALERT("%s: Addr.: 0x%08X, CB: %zu!\n", __FUNCTION__, addr, size); if((ret = ktiva_send_frame(pf, COMMAND_DOWNLOAD, data, sizeof(data))) == sizeof(data)) { ret = 0; } else { KALERT("%s - ktiva_send_frame failed: %d!\n", __FUNCTION__, ret); } return ret; } ///////////////////////////////////////////////////////////////////////////// int TivaCmdSendDataBlock(struct file *pf, const void *pBlock, size_t nCbBlock) { int ret; // KALERT("%s: Data: 0x%p, CB: %zu!\n", __FUNCTION__, pBlock, nCbBlock); if((ret = ktiva_send_frame(pf, COMMAND_SEND_DATA, pBlock, nCbBlock)) == nCbBlock) { ret = 0; } else { KALERT("%s - ktiva_send_frame failed: %d!\n", __FUNCTION__, ret); } return ret; } ///////////////////////////////////////////////////////////////////////////// int TivaCmdReset(struct file *pf) { int ret; if((ret = ktiva_send_frame(pf, COMMAND_RESET, NULL, 0)) != 0) { KALERT("%s - ktiva_send_frame failed: %d!\n", __FUNCTION__, ret); } return ret; } ///////////////////////////////////////////////////////////////////////////// int TivaCmdGetMatSer(struct file *pf, LPTIVA_MAT_SER pms) { int ret; TIVA_MAT_SER data; #if _EXTENDED_ERROR_CHECK if(!pms) { KALERT("%s: Invalid data pointer!\n", __FUNCTION__); return -EINVAL; } #endif // _EXTENDED_ERROR_CHECK if((ret = ktiva_send_frame(pf, COMMAND_GET_MAT_SER, NULL, 0)) == 0) { if((ret = ktiva_recv_bootloader_frame(pf, COMMAND_GET_MAT_SER, &data, sizeof(data))) == sizeof(data)) { memcpy(pms, &data, sizeof(data)); kspi_tx_byte(pf, CMD_ACK); ret = 0; } else { KALERT("%s - ktiva_recv_frame failed: %d\n", __FUNCTION__, ret); } } else { KALERT("%s - ktiva_send_frame failed: %d!\n", __FUNCTION__, ret); } return ret; } ///////////////////////////////////////////////////////////////////////////// int TivaCmdSetBacklight(struct file *pf, unsigned int nFrequency, unsigned int nBrightness) { int ret; unsigned int data[2] = {cpu_to_be32(nFrequency), cpu_to_be32(nBrightness * 10)}; if((ret = ktiva_send_frame(pf, COMMAND_SET_BACKLIGHT, data, sizeof(data))) == sizeof(data)) { ret = 0; } else { KALERT("%s - ktiva_send_frame failed: %d!\n", __FUNCTION__, ret); } return ret; }