From 588cfbc2c2db17b57cda94f9d20b2dd5d69ec4d3 Mon Sep 17 00:00:00 2001 From: Olaf Rempel Date: Sat, 1 Mar 2008 17:18:39 +0100 Subject: [PATCH] work work --- main.c | 173 +++++++++++++---------------- src/at91_adc.c | 98 ----------------- src/at91_rttc_test.c | 33 ------ src/at91_tc1.c | 227 -------------------------------------- src/at91_udp.c | 224 ++++++++++++++++++++++++------------- src/telemetrie.c | 255 ------------------------------------------- 6 files changed, 227 insertions(+), 783 deletions(-) delete mode 100644 src/at91_adc.c delete mode 100644 src/at91_rttc_test.c delete mode 100644 src/at91_tc1.c delete mode 100644 src/telemetrie.c diff --git a/main.c b/main.c index 477de44..003cdf6 100644 --- a/main.c +++ b/main.c @@ -1,95 +1,78 @@ -/*************************************************************************** - * Copyright (C) 01/2008 by Olaf Rempel * - * razzor@kopf-tisch.de * - * * - * 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; version 2 of the License * - * * - * 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., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "AT91SAM7S256.h" -#include "at91_sysc.h" -#include "at91_dbgu.h" -#include "at91_pitc.h" -#include "at91_tests.h" -#include "at91_udp.h" -#include "at91_pio.h" -#include "at91_twi.h" - -#include "at91_tc1.h" -#include "memalloc.h" - -#include "board.h" -#include -#include - -static uint32_t pitc_test(struct pitc_timer *timer) -{ - static uint32_t i; - *AT91C_PIOA_SODR = i; - i = i ^ LED_GREEN; - *AT91C_PIOA_CODR = i; -/* - struct rc_values rc; - uint32_t count = rcontrol_getvalues(&rc); - - printf("%ld channels: ", count); - uint32_t j; - for (j = 0; j < count; j++) - printf("%+5d ", rc.chan[j]); - - printf("\r"); -*/ - return PITC_RESTART_TIMER; -} - -static struct pitc_timer pitc_test_timer = { - .interval = 10, - .func = &pitc_test, -}; - -int main(void) -{ - /* LED outputs */ - *AT91C_PIOA_PER = LED_GREEN | LED_ORANGE; - *AT91C_PIOA_OER = LED_GREEN | LED_ORANGE; - - /* needed for dbgu */ - at91_sysc_init(); - - at91_dbgu_init(); - at91_dbgu_puts("==========================================================\n\rGood morning Dave\n\r"); - - /* triggers pinchange-isrs */ - at91_pio_init(); - - /* timer */ - at91_pitc_init(); - at91_rttc_test_init(); - at91_tc1_init(); - - /* adc, need timer */ - at91_adc_test_init(); - - /* twi */ - at91_twi_init(); - at91_twi_test(); - - /* usb */ - at91_udp_init(); - - printf("static alloc: %5ld bytes\n\r", static_alloc_used()); - - pitc_schedule_timer(&pitc_test_timer); - - while (1); -} +/*************************************************************************** + * Copyright (C) 01/2008 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * 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; version 2 of the License * + * * + * 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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "AT91SAM7S256.h" +#include "at91_sysc.h" +#include "at91_dbgu.h" +#include "at91_pitc.h" +#include "at91_udp.h" +#include "at91_pio.h" +#include "at91_twi.h" + +#include "memalloc.h" + +#include "board.h" +#include +#include + +static uint32_t pitc_test(struct pitc_timer *timer) +{ + static uint32_t i; + *AT91C_PIOA_SODR = i; + i = i ^ LED_GREEN; + *AT91C_PIOA_CODR = i; + + return PITC_RESTART_TIMER; +} + +static struct pitc_timer pitc_test_timer = { + .interval = 10, + .func = &pitc_test, +}; + +int main(void) +{ + /* LED outputs */ + *AT91C_PIOA_PER = LED_GREEN | LED_ORANGE; + *AT91C_PIOA_OER = LED_GREEN | LED_ORANGE; + + /* needed for dbgu */ + at91_sysc_init(); + + at91_dbgu_init(); + at91_dbgu_puts("==========================================================\n\rGood morning Dave\n\r"); + + /* triggers pinchange-isrs */ + at91_pio_init(); + + /* timer */ + at91_pitc_init(); + + /* twi */ + at91_twi_init(); + at91_twi_test(); + + /* usb */ + at91_udp_init(); + + printf("static alloc: %5ld bytes\n\r", static_alloc_used()); + + pitc_schedule_timer(&pitc_test_timer); + + while (1); +} diff --git a/src/at91_adc.c b/src/at91_adc.c deleted file mode 100644 index e5a1e15..0000000 --- a/src/at91_adc.c +++ /dev/null @@ -1,98 +0,0 @@ -/*************************************************************************** - * Copyright (C) 01/2008 by Olaf Rempel * - * razzor@kopf-tisch.de * - * * - * 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; version 2 of the License * - * * - * 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., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include - -#include "AT91SAM7S256.h" -#include "board.h" -#include "at91_pitc.h" - -static uint16_t adc_result[7]; - -static void at91_adc_isr(void) -{ - AT91S_PDC *pdc = AT91C_BASE_PDC_ADC; - pdc->PDC_RPR = (uint32_t) &adc_result; - pdc->PDC_RCR = ARRAY_SIZE(adc_result); - pdc->PDC_PTCR = AT91C_PDC_RXTEN; - - /* clear interrupts */ - AT91S_ADC *adc = AT91C_BASE_ADC; - uint32_t status = adc->ADC_SR; - status = status; -} - -static uint32_t adc_trigger(struct pitc_timer *timer) -{ - uint32_t i; - for (i = 0; i < ARRAY_SIZE(adc_result); i++) - printf("0x%03x ", adc_result[i]); - - printf("\n\r"); - - *AT91C_ADC_CR = AT91C_ADC_START; - return PITC_RESTART_TIMER; -} - -static struct pitc_timer adc_timer = { - .interval = 10, - .func = &adc_trigger, -}; - -void at91_adc_test_init(void) -{ - /* enable ADC clock */ - *AT91C_PMC_PCER = (1 << AT91C_ID_ADC); - - /* ADC Software reset */ - AT91S_ADC *adc = AT91C_BASE_ADC; - adc->ADC_CR = AT91C_ADC_SWRST; - - /* - * ADC config: 10bit, no sleep - * 4.8MHz (48MHz / ((4 +1) * 2) = 4.8MHz) - * 96 cycles Startup ((11 +1) * 8 / 4.8MHz = 20us) - * 3 cycles SH ((2 +1) / 4.8MHz = 625ns) - * Conversion time per channel @5MHz ~2us - */ - adc->ADC_MR = AT91C_ADC_TRGEN_DIS | - AT91C_ADC_LOWRES_10_BIT | - AT91C_ADC_SLEEP_NORMAL_MODE | - (AT91C_ADC_PRESCAL & (4 << 8)) | - (AT91C_ADC_STARTUP & (11 << 16)) | - (AT91C_ADC_SHTIM & (2 << 24)); - - /* setup PDC */ - AT91S_PDC *pdc = AT91C_BASE_PDC_ADC; - pdc->PDC_RPR = (uint32_t) &adc_result; - pdc->PDC_RCR = ARRAY_SIZE(adc_result); - pdc->PDC_PTCR = AT91C_PDC_RXTEN; - - /* enable 4 channels, PDC Interrupt */ - adc->ADC_CHER = 0xF7; - adc->ADC_IER = AT91C_ADC_ENDRX; - - /* low priority, level triggered, own vector */ - AT91S_AIC *aic = AT91C_BASE_AIC; - aic->AIC_SMR[AT91C_ID_ADC] = IRQPRIO_ADC | AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL; - aic->AIC_SVR[AT91C_ID_ADC] = (uint32_t)at91_adc_isr; - aic->AIC_IECR = (1< -#include "AT91SAM7S256.h" -#include "at91_sysc.h" -#include "board.h" - -static void rtt_isr(uint32_t status) -{ - *AT91C_RTTC_RTAR = *AT91C_RTTC_RTVR +1; - - static uint32_t i; - *AT91C_PIOA_SODR = i; - i = i ^ LED_ORANGE; - *AT91C_PIOA_CODR = i; -} - -void at91_rttc_test_init(void) -{ - /* calculate SLOWCK from MAINCK and measured MAINF */ - uint32_t prescaler = MAINCK * 16 / (*AT91C_CKGR_MCFR & AT91C_CKGR_MAINF); - - sysc_register_isr(AT91_SYSIRQ_RTT, &rtt_isr); - - /* - * AT91C_RTTC_RTTINCIEN doesn't work - * use AT91C_RTTC_ALMIEN and increment RTAR in isr - */ - *AT91C_RTTC_RTAR = *AT91C_RTTC_RTVR +1; - *AT91C_RTTC_RTMR = (AT91C_RTTC_RTPRES & prescaler) | - AT91C_RTTC_ALMIEN | - AT91C_RTTC_RTTRST; - - printf("rttc running at %ld Hz\n\r", prescaler); -} diff --git a/src/at91_tc1.c b/src/at91_tc1.c deleted file mode 100644 index 99a2870..0000000 --- a/src/at91_tc1.c +++ /dev/null @@ -1,227 +0,0 @@ -/*************************************************************************** - * Copyright (C) 01/2008 by Olaf Rempel * - * razzor@kopf-tisch.de * - * * - * 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; version 2 of the License * - * * - * 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., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include -#include /* abs() */ -#include "AT91SAM7S256.h" -#include "board.h" -#include "at91_tc1.h" -#include "at91_pio.h" - -/* Hard limits for ISR */ -#define PULSE_MIN 0x0500 -#define PULSE_MAX 0x0D00 -#define PULSE_TIMEOUT 0x0F00 -#define PULSE_CENTER 0x08C0 - -/* moving average filters */ -#define PULSE_FILTER_FAST (1<<2) -#define PULSE_FILTER_SLOW (1<<4) -#define PULSE_FILTER_DIFF 16 /* point to switch filters */ -#define PULSE_MID_DIFF 50 /* minimum diff to center */ - -#define VALUE_RANGE 256 - -#define ROUND_DIV256(x) ((x >> 8) + ((x & 0x80) ? 1 : 0)) - -struct channel_data { - uint16_t width; - uint16_t width_slow; - uint16_t filter; /* 0 - fast filter, 1 - slow filter */ - uint16_t min; /* minimum value during calibration */ - uint16_t mid; /* center value */ - uint16_t max; /* maximum value */ -}; - -static struct channel_data ch_data[MAX_CHANNELS]; -static uint32_t count, valid, cal_in_progress; - -static void ppm_isr(void) -{ - static uint32_t i; - - /* RC Compare -> no TIOA1 edge for 2.5ms */ - uint32_t status = *AT91C_TC1_SR; - - if (status & AT91C_TC_CPCS) { - /* average channel count */ - count = ((count * 7) + (i << 8)) / 8; - - /* at least 4 channels and a stable channel count */ - if ((ROUND_DIV256(count) == i) && (i >= 4)) { - if (valid < 10) - valid++; - - } else if (valid > 0) { - valid--; - } - - /* reset index */ - i = 0; - } - - /* edge on TIOA1 */ - if (status & AT91C_TC_LDRAS) { - /* get impulse width */ - uint16_t width = *AT91C_TC1_RA; - - /* valid range: 1 - 2ms */ - if (width > PULSE_MIN && width < PULSE_MAX) { - if (i < ARRAY_SIZE(ch_data)) { - /* calc both filters */ - ch_data[i].width = ((ch_data[i].width * (PULSE_FILTER_FAST -1)) + width) / PULSE_FILTER_FAST; - ch_data[i].width_slow = ((ch_data[i].width_slow * (PULSE_FILTER_SLOW -1)) + width) / PULSE_FILTER_SLOW; - - if (cal_in_progress) { - /* use slow filter values, calc center */ - ch_data[i].min = MIN(ch_data[i].width_slow, ch_data[i].min); - ch_data[i].max = MAX(ch_data[i].width_slow, ch_data[i].max); - ch_data[i].mid = (ch_data[i].min + ch_data[i].max) / 2; - } - } - i++; - } - } -} - -uint32_t rcontrol_getvalues(struct rc_values *rc) -{ - if (valid < 5) - return 0; - - uint32_t i; - uint32_t cnt = MIN(ROUND_DIV256(count), ARRAY_SIZE(ch_data)); - for (i = 0; i < cnt; i++) { - /* switch between fast and slow filter */ - uint16_t filter = (abs(ch_data[i].width - ch_data[i].width_slow) < PULSE_FILTER_DIFF); - - /* - * transition fast -> slow filter - * slow filter is lagging behind, so give it a boost - */ - if (filter && !ch_data[i].filter && !cal_in_progress) - ch_data[i].width_slow = ch_data[i].width; - - ch_data[i].filter = filter; - - uint16_t width = (filter) ? ch_data[i].width_slow : ch_data[i].width; - - /* expand the value to +/- VALUE_RANGE */ - int32_t tmp = (width - ch_data[i].mid) * VALUE_RANGE; - tmp = tmp / ((tmp > 0) ? (ch_data[i].max - ch_data[i].mid) : (ch_data[i].mid - ch_data[i].min)); - - /* keep result in range */ - if (tmp > VALUE_RANGE) - tmp = VALUE_RANGE; - - if (tmp < -VALUE_RANGE) - tmp = -VALUE_RANGE; - - rc->chan[i] = tmp; - } - return cnt; -} - -void rcontrol_calibrate(uint32_t mode) -{ - uint32_t i; - - switch (mode) { - case RC_CAL_START: - cal_in_progress = 1; - for (i = 0; i < ARRAY_SIZE(ch_data); i++) { - /* use hard limits as hint */ - ch_data[i].max = PULSE_MIN; - ch_data[i].mid = (PULSE_MIN + PULSE_MAX) / 2; - ch_data[i].min = PULSE_MAX; - } - break; - - case RC_CAL_END: - cal_in_progress = 0; - for (i = 0; i < ARRAY_SIZE(ch_data); i++) { - /* treat current position as center */ - ch_data[i].mid = ch_data[i].width_slow; - - /* if center is near minimum, clamp output to 0..+1024 */ - if (ch_data[i].mid - ch_data[i].min < PULSE_MID_DIFF) - ch_data[i].mid = ch_data[i].min; - - /* if center is near maximum, clamp output to -1024..0 */ - if (ch_data[i].max - ch_data[i].mid < PULSE_MID_DIFF) - ch_data[i].mid = ch_data[i].max; - } - break; - } -} - -void rcontrol_print_cal(void) -{ - uint32_t i; - for (i = 0; i < ARRAY_SIZE(ch_data); i++) { - printf("%ld: %d(%+d) - %d(0) - %d(%+d)\n\r", i, - ch_data[i].min, ch_data[i].min - ch_data[i].mid, - ch_data[i].mid, - ch_data[i].max, ch_data[i].max - ch_data[i].mid - ); - } -} - -void at91_tc1_init(void) -{ - /* enable TC1 clock */ - *AT91C_PMC_PCER = (1 << AT91C_ID_TC1); - - /* MCK /32, trigger & capture on falling TIOA1 edge */ - *AT91C_TC1_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | AT91C_TC_LDRA_FALLING | - AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG; - - /* enable RA load and RC compare interrupt */ - *AT91C_TC1_IER = AT91C_TC_LDRAS | AT91C_TC_CPCS; - - /* RC Compare Interrupt if no rising Edge on TIOA1 for 2.56ms */ - *AT91C_TC1_RC = PULSE_TIMEOUT; - - /* enable & trigger the clock */ - *AT91C_TC1_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - - /* level triggered, own vector */ - AT91S_AIC *aic = AT91C_BASE_AIC; - aic->AIC_SMR[AT91C_ID_TC1] = IRQPRIO_TC1 | AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL; - aic->AIC_SVR[AT91C_ID_TC1] = (uint32_t)ppm_isr; - aic->AIC_IECR = (1 << AT91C_ID_TC1); -} - -static void tast_monitor(uint32_t status, uint32_t input) -{ - if (!(input & TAST1) && (cal_in_progress == 0)) { - printf("start calibration\n\r"); - - rcontrol_calibrate(RC_CAL_START); - - - } else if (!(input & TAST2) && (cal_in_progress == 1)) { - printf("end calibration\n\r"); - - rcontrol_calibrate(RC_CAL_END); - rcontrol_print_cal(); - } -} - -PIO_PINCHANGE_ISR(TAST1 | TAST2, tast_monitor); diff --git a/src/at91_udp.c b/src/at91_udp.c index 2fec7ee..0fde2ba 100644 --- a/src/at91_udp.c +++ b/src/at91_udp.c @@ -24,6 +24,7 @@ #include "usb_ch9.h" #include "usb_cdc.h" +#include "usb_dfu.h" #define csr_clear_flags(csr, flags) \ while ((csr) & (flags)) \ @@ -76,17 +77,76 @@ static const struct usb_device_descriptor dev_descriptor = { .bNumConfigurations = 1, }; +static const struct usb_string_descriptor usb_string0 = { + /* String 0 - Language */ + .bLength = sizeof(struct usb_string_descriptor) + 1 * sizeof(uint16_t), + .bDescriptorType = USB_DT_STRING, + .wData = { 0x0409 /* English */ }, +}; + +static const struct usb_string_descriptor usb_string1 = { + /* String 1 "sam7fc-flash" */ + .bLength = sizeof(struct usb_string_descriptor) + 12 * sizeof(uint16_t), + .bDescriptorType = USB_DT_STRING, + .wData = { + 0x0073, 0x0061, 0x006d, 0x0037, 0x0066, 0x0063, 0x002d, 0x0066, + 0x006c, 0x0061, 0x0073, 0x0068, + }, +}; + +static const struct usb_string_descriptor usb_string2 = { + /* String 2 "blctrl1-flash" */ + .bLength = sizeof(struct usb_string_descriptor) + 13 * sizeof(uint16_t), + .bDescriptorType = USB_DT_STRING, + .wData = { + 0x0062, 0x006c, 0x0063, 0x0074, 0x0072, 0x006c, 0x0031, 0x002d, + 0x0066, 0x006c, 0x0061, 0x0073, 0x0068, + }, +}; + +static const struct usb_string_descriptor usb_string3 = { + /* String 3 "blctrl2-flash" */ + .bLength = sizeof(struct usb_string_descriptor) + 13 * sizeof(uint16_t), + .bDescriptorType = USB_DT_STRING, + .wData = { + 0x0062, 0x006c, 0x0063, 0x0074, 0x0072, 0x006c, 0x0032, 0x002d, + 0x0066, 0x006c, 0x0061, 0x0073, 0x0068, + }, +}; + +static const struct usb_string_descriptor usb_string4 = { + /* String 4 "blctrl3-flash" */ + .bLength = sizeof(struct usb_string_descriptor) + 13 * sizeof(uint16_t), + .bDescriptorType = USB_DT_STRING, + .wData = { + 0x0062, 0x006c, 0x0063, 0x0074, 0x0072, 0x006c, 0x0033, 0x002d, + 0x0066, 0x006c, 0x0061, 0x0073, 0x0068, + }, +}; + +static const struct usb_string_descriptor usb_string5 = { + /* String 5 "blctrl4-flash" */ + .bLength = sizeof(struct usb_string_descriptor) + 13 * sizeof(uint16_t), + .bDescriptorType = USB_DT_STRING, + .wData = { + 0x0062, 0x006c, 0x0063, 0x0074, 0x0072, 0x006c, 0x0034, 0x002d, + 0x0066, 0x006c, 0x0061, 0x0073, 0x0068, + }, +}; + +static const struct usb_string_descriptor *usb_strings[] = { + &usb_string0, &usb_string1, &usb_string2, &usb_string3, + &usb_string4, &usb_string5, +}; + struct my_config { struct usb_config_descriptor cfg; - struct usb_interface_descriptor ctrl_iface; - struct usb_cdc_header_desc cdc_header; - struct usb_cdc_call_mgmt_descriptor cdc_call_mgmt; - struct usb_cdc_acm_descriptor cdc_acm; - struct usb_cdc_union_desc cdc_union; - struct usb_endpoint_descriptor notify_ep; - struct usb_interface_descriptor data_iface; - struct usb_endpoint_descriptor dataout_ep; - struct usb_endpoint_descriptor datain_ep; + struct usb_interface_descriptor iface0; + struct usb_interface_descriptor iface1; + struct usb_interface_descriptor iface2; + struct usb_interface_descriptor iface3; + struct usb_interface_descriptor iface4; + struct usb_dfu_descriptor dfu; } __attribute__ ((packed)); static const struct my_config cfg_descriptor = { @@ -94,82 +154,81 @@ static const struct my_config cfg_descriptor = { .bLength = sizeof(struct usb_config_descriptor), .bDescriptorType = USB_DT_CONFIG, .wTotalLength = sizeof(struct my_config), - .bNumInterfaces = 2, + .bNumInterfaces = 1, .bConfigurationValue = 1, .bmAttributes = USB_CONFIG_ATT_SELFPOWER | USB_CONFIG_ATT_WAKEUP, .bMaxPower = 50, }, -.ctrl_iface = { +.iface0 = { .bLength = sizeof(struct usb_interface_descriptor), .bDescriptorType = USB_DT_INTERFACE, .bInterfaceNumber = 0, - .bNumEndpoints = 1, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, - .bInterfaceProtocol = 1, + .bInterfaceClass = USB_CLASS_APP_SPEC, + .bInterfaceSubClass = 0x01, /* DFU */ + .bInterfaceProtocol = 0x02, + .iInterface = 0x01, }, -.cdc_header = { - .bLength = sizeof(struct usb_cdc_header_desc), - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = 0x0110, -}, -.cdc_call_mgmt = { - .bLength = sizeof(struct usb_cdc_call_mgmt_descriptor), - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, - .bmCapabilities = USB_CDC_CALL_MGMT_CAP_CALL_MGMT, - .bDataInterface = 1, -}, -.cdc_acm = { - .bLength = sizeof(struct usb_cdc_acm_descriptor), - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_ACM_TYPE, - .bmCapabilities = (USB_CDC_CAP_BRK | USB_CDC_CAP_LINE | USB_CDC_COMM_FEATURE), -}, -.cdc_union = { - .bLength = sizeof(struct usb_cdc_union_desc), - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_UNION_TYPE, - .bMasterInterface0 = 0, - .bSlaveInterface0 = 1, -}, -.notify_ep = { - .bLength = sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN | 0x03, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = 64, - .bInterval = 10, -}, -.data_iface = { +.iface1 = { .bLength = sizeof(struct usb_interface_descriptor), .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 1, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_CDC_DATA, + .bInterfaceNumber = 0, + .bAlternateSetting = 1, + .bInterfaceClass = USB_CLASS_APP_SPEC, + .bInterfaceSubClass = 0x01, /* DFU */ + .bInterfaceProtocol = 0x02, + .iInterface = 0x02, }, -.dataout_ep = { - .bLength = sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_OUT | 0x01, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = 64, +.iface2 = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 2, + .bInterfaceClass = USB_CLASS_APP_SPEC, + .bInterfaceSubClass = 0x01, /* DFU */ + .bInterfaceProtocol = 0x02, + .iInterface = 0x03, }, -.datain_ep = { - .bLength = sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN | 0x02, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = 64, +.iface3 = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 3, + .bInterfaceClass = USB_CLASS_APP_SPEC, + .bInterfaceSubClass = 0x01, /* DFU */ + .bInterfaceProtocol = 0x02, + .iInterface = 0x04, }, +.iface4 = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 4, + .bInterfaceClass = USB_CLASS_APP_SPEC, + .bInterfaceSubClass = 0x01, /* DFU */ + .bInterfaceProtocol = 0x02, + .iInterface = 0x05, +}, +.dfu = { + .bLength = sizeof(struct usb_dfu_descriptor), + .bDescriptorType = USB_TYPE_DFU, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_CAN_UPLOAD, + .wDetachTimeOut = 0xff00, + .wTransferSize = AT91C_IFLASH_PAGE_SIZE, + .bcdDFUVersion = 0x0101, +}, +}; + +static struct dfu_status dfu_status = { + .bStatus = DFU_STATUS_OK, + .bwPollTimeout = {0x00, 0x04, 0x00}, + .bState = DFU_STATE_dfuIDLE, }; static void ep_transfer_send(uint32_t ep, char *data, uint32_t length, void (*complete_cb)(void)) { struct ep_ctx *ctx = &ep_ctx[ep]; -// printf("ep_transfer_send(%ld) size=%ld flags=0x%x\n\r", ep, length, ctx->flags); + printf("ep_transfer_send(%ld) size=%ld flags=0x%x\n\r", ep, length, ctx->flags); if (!(ctx->flags & CTX_TRANSFER) || (ctx->flags & (CTX_IN | CTX_OUT))) return; @@ -196,7 +255,7 @@ static void ep_transfer_receive(uint32_t ep, char *data, uint32_t length, void (*complete_cb)(void)) { struct ep_ctx *ctx = &ep_ctx[ep]; -// printf("ep_transfer_receive(%ld) size=%ld flags=0x%x\n\r", ep, length, ctx->flags); + printf("ep_transfer_receive(%ld) size=%ld flags=0x%x\n\r", ep, length, ctx->flags); if (!(ctx->flags & CTX_TRANSFER) || (ctx->flags & (CTX_IN | CTX_OUT))) return; @@ -242,6 +301,7 @@ static void udp_configure_ep(const struct usb_endpoint_descriptor *desc) */ static void udp_txcb_setaddress(void) { + printf("usb address: %d\n\r", current_address); *AT91C_UDP_FADDR = (AT91C_UDP_FEN | current_address); *AT91C_UDP_GLBSTATE = AT91C_UDP_FADDEN; } @@ -252,10 +312,7 @@ static void udp_txcb_setaddress(void) */ static void udp_txcb_setconfig(void) { - udp_configure_ep(&cfg_descriptor.notify_ep); - udp_configure_ep(&cfg_descriptor.datain_ep); - udp_configure_ep(&cfg_descriptor.dataout_ep); - + printf("usb configuration: %d\n\r", current_config); /* set UDP to "configured" */ *AT91C_UDP_GLBSTATE = AT91C_UDP_CONFG; } @@ -292,6 +349,19 @@ static void ep_handle_ctrlrequest(struct usb_ctrlrequest *req) NULL); break; + case USB_DT_STRING: /* 0x03 */ + ; + uint8_t index = req->wValue & 0xFF; + if (index < ARRAY_SIZE(usb_strings)) { + printf("get string %d: %p\n\r", index, usb_strings[index]); + ep_transfer_send(0, (char *)usb_strings[index], + MIN(usb_strings[index]->bLength, req->wLength), + NULL); + } else { + ep_send_stall(0); + } + break; + default: ep_send_stall(0); break; @@ -326,12 +396,14 @@ static void ep_handle_ctrlrequest(struct usb_ctrlrequest *req) case (USB_TYPE_CLASS | USB_RECIP_INTERFACE): /* 0x21/0xA1 */ // TODO: follow current_interface switch (req->bRequest) { - case USB_CDC_REQ_SET_LINE_CODING: /* 0x20 */ - /* read 7 bytes */ + case USB_REQ_DFU_DETACH: /* 0x00 */ + ep_transfer_send(0, NULL, 0, NULL); break; - case USB_CDC_REQ_SET_CONTROL_LINE_STATE: /* 0x22 */ - ep_transfer_send(0, NULL, 0, NULL); + case USB_REQ_DFU_GETSTATUS: /* 0x03 */ + ep_transfer_send(0, (char *)&dfu_status, + MIN(sizeof(struct dfu_status), req->wLength), + NULL); break; default: @@ -396,6 +468,8 @@ static void udp_handle_ep(uint32_t ep) } else { ctx->flags &= ~CTX_IN; + printf("txcomp\n\r"); + if (transfer->complete_cb) transfer->complete_cb(); } diff --git a/src/telemetrie.c b/src/telemetrie.c deleted file mode 100644 index 4df776c..0000000 --- a/src/telemetrie.c +++ /dev/null @@ -1,255 +0,0 @@ -/*************************************************************************** - * Copyright (C) 02/2008 by Olaf Rempel * - * razzor@kopf-tisch.de * - * * - * 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; version 2 of the License * - * * - * 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., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include -#include -#include "board.h" // ARRAY_SIZE() -#include "at91_pitc.h" -#include "telemetrie.h" -#include "memalloc.h" -#include "fifo.h" - -/* extern symbols, defined in ldscript */ -extern struct tdc_value _tdc_value_table; -extern struct tdc_value _tdc_value_table_end; - -/* max. 8x 32 = 256 variables */ -static uint32_t tdc_varmap[8]; - -/* array of devices, that are used to reach address X */ -static struct comm_device *routing_table[8]; - -/* - * returns: - * -1: on routing error - * 0: no space left in txfifo (caller should retry) - * >0: success - */ -int32_t tdc_transmit(uint32_t addr, struct tdc_pkt_header *head) -{ - if (addr >= ARRAY_SIZE(routing_table) || !routing_table[addr]) - return -1; - - return fifo_put(routing_table[addr]->txfifo, (char *)head, head->size); -} - -static int32_t tdc_get_vars(void) -{ - /* restart point */ - static uint32_t id; - - struct tdc_value *value = &_tdc_value_table + id; - - while (value < &_tdc_value_table_end) { - uint32_t datalen = strlen(value->name); - - struct tdc_getvars_reply *reply = alloc(sizeof(struct tdc_getvars_reply) + datalen); - reply->cmd = TDC_REPLY | TDC_ADDR1 | TDC_GETVARS; - reply->size = sizeof(struct tdc_getvars_reply) + datalen; - reply->id = id; - reply->flags = value->flags; - memcpy(reply->name, value->name, datalen); - - uint32_t ret = tdc_transmit(TDC_ADDR0, ((struct tdc_pkt_header *)reply)); - free(reply); - - /* push routing error(-1) and retry(0) */ - if (ret <= 0) - return ret; - - id++; - value++; - } - - /* dump complete, reset restart point */ - id = 0; - return 1; -} - -static int32_t tdc_get_value(uint32_t id) -{ - struct tdc_value *value = &_tdc_value_table + id; - if (value >= &_tdc_value_table_end) - return -1; - - uint32_t datalen = value->flags & TDC_SIZEMASK; - - struct tdc_getvalue_reply *reply = alloc(sizeof(struct tdc_getvalue_reply) + datalen); - reply->cmd = TDC_REPLY | TDC_ADDR1 | TDC_GETVALUE; - reply->size = sizeof(struct tdc_getvars_reply) + datalen; - reply->id = id; - memcpy(reply->data, value->data, datalen); - - int32_t ret = tdc_transmit(TDC_ADDR0, ((struct tdc_pkt_header *)reply)); - free(reply); - - return ret; -} - -static int32_t tdc_set_value(uint32_t id, uint8_t *data) -{ - struct tdc_value *value = &_tdc_value_table + id; - if (value >= &_tdc_value_table_end) - return -1; - - uint32_t datalen = value->flags & TDC_SIZEMASK; - - // TODO: atomic? - memcpy(value->data, data, datalen); - - return 1; -} - -static uint32_t tdc_timer_cb(struct pitc_timer *timer) -{ - uint32_t i, j; - for (i = 0; i < ARRAY_SIZE(tdc_varmap); i++) { - uint32_t tmp = tdc_varmap[i]; - - for (j = 0; j < 32; j++) { - if (!tmp) - break; - - if (tmp & 0x01) { - if (tdc_get_value(i * 32 + j) <= 0) - return PITC_REMOVE_TIMER; - } - - tmp >>= 1; - } - } - return PITC_RESTART_TIMER; -} - -static struct pitc_timer tdc_timer = { - .func = tdc_timer_cb, -}; - -static int32_t tdc_setup_timer(uint32_t interval, uint32_t *varmap) -{ - memcpy(tdc_varmap, varmap, sizeof(tdc_varmap)); - - if (interval > 0) { - tdc_timer.interval = interval; - // TODO: timer already running - pitc_schedule_timer(&tdc_timer); - - } else { - // TODO: timer stop - } - return 1; -} - -static const struct tdc_hello_reply hello_reply = { - .cmd = TDC_REPLY | TDC_ADDR1 | TDC_HELLO, - .size = sizeof(struct tdc_hello_reply), - .name = "sam7fc-v0.01", -}; - -/* - * returns: - * -1: on routing error - * 0: no space left in txfifo (caller should retry) - * >0: success - */ -static int32_t tdc_parse_packet(struct tdc_pkt_header *head) -{ - /* all replys go to the HOST */ - if (head->cmd & TDC_REPLY) - return tdc_transmit(TDC_ADDR0, head); - - /* forward this packet? */ - if ((head->cmd & TDC_ADDRMASK) != TDC_ADDR1) { - uint32_t addr = (head->cmd & TDC_ADDRMASK) >> 4; - return tdc_transmit(addr, head); - } - - int32_t ret = -1; - - /* parse the packet */ - switch (head->cmd & TDC_OPCODEMASK) { - case TDC_HELLO: - /* answer the hello */ - ret = tdc_transmit(TDC_ADDR0, (struct tdc_pkt_header *)&hello_reply); - break; - - case TDC_GETVARS: - ret = tdc_get_vars(); - break; - - case TDC_GETVALUE: { - struct tdc_getvalue_request *pkt = (struct tdc_getvalue_request *)head; - ret = tdc_get_value(pkt->id); - } break; - - case TDC_SETVALUE: { - struct tdc_setvalue_request *pkt = (struct tdc_setvalue_request *)head; - ret = tdc_set_value(pkt->id, pkt->data); - } break; - - case TDC_REQVALUES: { - struct tdc_reqvalues_request *pkt = (struct tdc_reqvalues_request *)head; - ret = tdc_setup_timer(pkt->interval, pkt->varmap); - } break; - }; - - /* - * on succes(>0) return size of request, - * and push retry(0) and routing error(-1) up - */ - return (ret > 0) ? head->size : ret; -} - -void tdc_register_device(uint32_t addr, struct comm_device *device) -{ - if (addr < ARRAY_SIZE(routing_table)) - routing_table[addr] = device; -} - -void tdc_receive(struct comm_device *device) -{ - while (1) { - /* peek the header */ - struct tdc_pkt_header tmp_head; - uint32_t len = fifo_peek(device->rxfifo, (char *)&tmp_head, sizeof(tmp_head)); - if (len != sizeof(tmp_head)) - return; - - /* peek the whole packet */ - struct tdc_pkt_header *head = alloc(tmp_head.size); - len = fifo_peek(device->rxfifo, (char *)head, tmp_head.size); - if (len != tmp_head.size) - return; - - /* if it's a hello-request, remember the device as path to the host */ - if ((head->cmd & (TDC_OPCODEMASK & TDC_DIR)) == TDC_HELLO) - tdc_register_device(TDC_ADDR0, device); - - /* parse packet, remove data if no restart is needed */ - int32_t ret = tdc_parse_packet(head); - free(head); - - /* some tx-fifo was full(0), return to caller and let it retry */ - if (!ret) - return; - - /* success(>0) or routing error(-1) -> remove the packet */ - fifo_remove(device->rxfifo, tmp_head.size); - } -}