diff --git a/Makefile b/Makefile index a13c7dae31d512b764d3a622d093d30779061e86..8499dc1db7486f8a13be612e477d253d48b3418f 100755 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ include ../../STM32_processor/libraries/f4/select_processor.mk STM32_LIB_PATH = ../../STM32_processor/libraries/f4/stm32_lib STM32_DSP_LIB_PATH = ../../STM32_processor/libraries/f4/stm32_dsp_lib -DYNAMIXEL_LIB_PATH = ../../STM32_processor/libraries/f4/dynamixel +DYNAMIXEL_LIB_PATH = ../../STM32_processor/libraries STM32_STARTUP_FILES_PATH = ../../STM32_processor/startup/f4 STM32_LINKER_SCRIPTS_PATH = ../../STM32_processor/libraries/f4/linker_scripts BUILD_PATH=build @@ -18,7 +18,7 @@ COMPILE_OPTS = -mlittle-endian -mcpu=cortex-m4 -mthumb -mthumb-interwork COMPILE_OPTS += -Wall -g -O2 -fno-common COMPILE_OPTS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 COMPILE_OPTS += -ffreestanding -nostdlib -D$(PROCESSOR_MACRO) -DARM_MATH_CM4 -D__FPU_PRESENT -DHSE_VALUE=8000000 -INCLUDE_DIRS = -I$(STM32_LIB_PATH)/include -I$(STM32_LIB_PATH)/include/core -I$(STM32_LIB_PATH)/include/devices -I$(STM32_DSP_LIB_PATH)/include -I${DYNAMIXEL_LIB_PATH}/include -I./include +INCLUDE_DIRS = -I$(STM32_LIB_PATH)/include -I$(STM32_LIB_PATH)/include/core -I$(STM32_LIB_PATH)/include/devices -I$(STM32_DSP_LIB_PATH)/include -I${DYNAMIXEL_LIB_PATH}/include/dynamixel -I./include LIBRARY_DIRS = -L$(STM32_LIB_PATH)/lib -L$(STM32_DSP_LIB_PATH)/lib -L$(DYNAMIXEL_LIB_PATH)/lib -L/usr/arm-none-eabi/lib/fpu/ TCHAIN_PREFIX=arm-none-eabi- @@ -56,7 +56,7 @@ $(BUILD_PATH)/%.o: src/%.c $(CC) -c $(CFLAGS) -o $@ $< $(MAIN_OUT_ELF): mkdir_build $(BIOLOID_OBJS) $(BUID_PATH)/$(STARTUP_FILE:.s=.o) $(STM32_LIB_PATH)/lib/$(LIBRARY) - $(LD) $(LDFLAGS) $(BIOLOID_OBJS) $(BUILD_PATH)/$(STARTUP_FILE:.s=.o) $(STM32_LIB_PATH)/lib/$(LIBRARY) $(STM32_DSP_LIB_PATH)/lib/libstm32f4_dsp.a ${DYNAMIXEL_LIB_PATH}/lib/dynamixel.a -lm --output $@ + $(LD) $(LDFLAGS) $(BIOLOID_OBJS) $(BUILD_PATH)/$(STARTUP_FILE:.s=.o) $(STM32_LIB_PATH)/lib/$(LIBRARY) $(STM32_DSP_LIB_PATH)/lib/libstm32f4_dsp.a ${DYNAMIXEL_LIB_PATH}/lib/dynamixel_hard.a -lm --output $@ $(MAIN_OUT_HEX): $(MAIN_OUT_ELF) $(OBJCP) $(OBJCPFLAGS_HEX) $< $@ diff --git a/include/comm.h b/include/comm.h new file mode 100644 index 0000000000000000000000000000000000000000..1e8c7b8292bc8b1808ac192b4205707a2e0098df --- /dev/null +++ b/include/comm.h @@ -0,0 +1,10 @@ +#ifndef _COMM_H +#define _COMM_H + +#include "stm32f4xx.h" + +// public functions +void comm_init(void); +void comm_start(void); + +#endif diff --git a/include/dynamixel_master_uart_dma.h b/include/dynamixel_master_uart_dma.h index 41b651422fdfe979e25c933fb628e97b3c2e65e5..74763f75ea18c811eef55ef12eec2013a443a169 100755 --- a/include/dynamixel_master_uart_dma.h +++ b/include/dynamixel_master_uart_dma.h @@ -3,25 +3,38 @@ #include "stm32f4xx.h" #include "dynamixel.h" +#include "dynamixel2.h" // dynamixel master functions void dyn_master_init(void); -void dyn_master_flush(void); +void dyn_master_reset(void); void dyn_master_set_timeout(uint16_t timeout_ms); void dyn_master_scan(uint8_t *num,uint8_t *ids); +void dyn2_master_scan(uint8_t *num,uint8_t *ids); inline void dyn_master_enable_power(void); inline void dyn_master_disable_power(void); uint8_t dyn_master_is_power_enabled(void); uint8_t dyn_master_ping(uint8_t id); +uint8_t dyn2_master_ping(uint8_t id); uint8_t dyn_master_read_byte(uint8_t id,uint8_t address,uint8_t *data); +uint8_t dyn2_master_read_byte(uint8_t id,uint16_t address,uint8_t *data); uint8_t dyn_master_read_word(uint8_t id,uint8_t address,uint16_t *data); +uint8_t dyn2_master_read_word(uint8_t id,uint16_t address,uint16_t *data); uint8_t dyn_master_read_table(uint8_t id,uint8_t address,uint8_t length,uint8_t *data); +uint8_t dyn2_master_read_table(uint8_t id,uint16_t address,uint16_t length,uint8_t *data); uint8_t dyn_master_write_byte(uint8_t id, uint8_t address, uint8_t data); +uint8_t dyn2_master_write_byte(uint8_t id, uint16_t address, uint8_t data); uint8_t dyn_master_write_word(uint8_t id, uint8_t address, uint16_t data); +uint8_t dyn2_master_write_word(uint8_t id, uint16_t address, uint16_t data); uint8_t dyn_master_write_table(uint8_t id, uint8_t address, uint8_t length, uint8_t *data); +uint8_t dyn2_master_write_table(uint8_t id, uint16_t address, uint16_t length, uint8_t *data); uint8_t dyn_master_reg_write(uint8_t id, uint8_t address, uint8_t length, uint8_t *data); -void dyn_master_action(void); -void dyn_master_sync_write(uint8_t num,uint8_t *ids,uint8_t address, uint8_t length, uint8_t *data); +uint8_t dyn2_master_reg_write(uint8_t id, uint16_t address, uint16_t length, uint8_t *data); +uint8_t dyn_master_action(void); +uint8_t dyn2_master_action(void); +uint8_t dyn_master_sync_write(uint8_t num,uint8_t *ids,uint8_t address, uint8_t length, TWriteData *data); +uint8_t dyn2_master_sync_write(uint8_t num,uint8_t *ids,uint16_t address, uint16_t length, TWriteData *data); +uint8_t dyn_master_bulk_read(uint8_t num,uint8_t *ids,uint8_t *address, uint8_t *length, TWriteData *data); // repeater functions uint8_t dyn_master_resend_inst_packet(uint8_t *inst_packet, uint8_t *status_packet); diff --git a/include/ram.h b/include/ram.h index 485bf26b1bd8aebb1aeebd3a517eec875c457763..b0fb2f38647139114d271535c28eac76d3f8418d 100644 --- a/include/ram.h +++ b/include/ram.h @@ -17,7 +17,8 @@ typedef enum { BIOLOID_ID = DEVICE_ID_OFFSET, BIOLOID_BAUD_RATE = BAUDRATE_OFFSET, BIOLOID_RETURN_DELAY_TIME = RETURN_DELAY_OFFSET, - BIOLOID_MM_PERIOD = MM_PERIOD_OFFSET, + BIOLOID_MM_PERIOD_L = MM_PERIOD_OFFSET, + BIOLOID_MM_PERIOD_H = MM_PERIOD_OFFSET+1, BIOLOID_RETURN_LEVEL = RETURN_LEVEL_OFFSET, BIOLOID_DXL_POWER = 0x18, BIOLOID_LED = 0x19, @@ -127,14 +128,14 @@ typedef enum { BIOLOID_ACTION_PAGE = 0x81, BIOLOID_ACTION_CONTROL = 0x82, BIOLOID_ACTION_STATUS = 0x83, - BIOLOID_MM_PELVIS_ROLL_L = 0x84, - BIOLOID_MM_PELVIS_ROLL_R = 0x85, - BIOLOID_MM_ANKLE_ROLL_L = 0x86, - BIOLOID_MM_ANKLE_ROLL_R = 0x87, - BIOLOID_MM_ANKLE_PITCH_L = 0x88, - BIOLOID_MM_ANKLE_PITCH_R = 0x89, - BIOLOID_MM_KNEE_L = 0x8A, - BIOLOID_MM_KNEE_R = 0x8B + BIOLOID_MM_PELVIS_ROLL_GAIN_L = 0x84, + BIOLOID_MM_PELVIS_ROLL_GAIN_R = 0x85, + BIOLOID_MM_ANKLE_ROLL_GAIN_L = 0x86, + BIOLOID_MM_ANKLE_ROLL_GAIN_R = 0x87, + BIOLOID_MM_ANKLE_PITCH_GAIN_L = 0x88, + BIOLOID_MM_ANKLE_PITCH_GAIN_R = 0x89, + BIOLOID_MM_KNEE_GAIN_L = 0x8A, + BIOLOID_MM_KNEE_GAIN_R = 0x8B } bioloid_registers; #define RAM_SIZE 256 diff --git a/include/time.h b/include/time.h index 74f51f2d0d5b1624f5fe86827db7c4db7bb20215..365b6663a0dfa279d807047263be25cb3e37f0c0 100755 --- a/include/time.h +++ b/include/time.h @@ -6,5 +6,6 @@ void time_init(void); void delay_ms(__IO uint32_t time); +void delay_us(uint32_t us); #endif diff --git a/linker_script/STM32F4_1024FLASH_192RAM.ld b/linker_script/STM32F4_1024FLASH_192RAM.ld index 73182b00d9d292c59164baa5873c626f3b084add..818b7c4effa8498f31a11360c3645973c2ef7132 100644 --- a/linker_script/STM32F4_1024FLASH_192RAM.ld +++ b/linker_script/STM32F4_1024FLASH_192RAM.ld @@ -42,8 +42,8 @@ MEMORY { FLASH1 (rx) : ORIGIN = 0x08000000, LENGTH = 16K EEPROM (rw) : ORIGIN = 0x08004000, LENGTH = 32K -FLASH2 (rx) : ORIGIN = 0x0800C000, LENGTH = 848K -PAGES (r) : ORIGIN = 0x080E0000, LENGTH = 128K +PAGES (r) : ORIGIN = 0x0800C000, LENGTH = 128K +FLASH2 (rx) : ORIGIN = 0x0802C000, LENGTH = 848K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K } diff --git a/src/bioloid_stm32.c b/src/bioloid_stm32.c index 727737562acd0291a324b6c39a2fa9cf135fa038..81b5f694ee79e66cfa1109e5e7373f0e4551ed13 100644 --- a/src/bioloid_stm32.c +++ b/src/bioloid_stm32.c @@ -13,116 +13,10 @@ #include "motion_pages.h" #include "motion_manager.h" #include "action.h" - -uint8_t read_operation(uint8_t address, uint8_t length, uint8_t *data) -{ - uint8_t error; - - // pre-read operation - // read operation - error=ram_read_table(address,length,data); - // post-read operation - if(ram_in_range(BIOLOID_PUSHBUTTON,BIOLOID_PUSHBUTTON,address,length)) - ram_data[BIOLOID_PUSHBUTTON]=0x00; - - return error; -} - -uint8_t write_operation(uint8_t address,uint8_t length, uint8_t *data) -{ - uint8_t error,byte_value,i,j,do_op=0x00; - uint16_t word_value; - - // pre-write operation - if(ram_in_range(BIOLOID_DXL_POWER,BIOLOID_DXL_POWER,address,length)) - { - if(data[BIOLOID_DXL_POWER-address]&0x01) dyn_master_enable_power(); - else dyn_master_disable_power(); - } - if(ram_in_range(BIOLOID_LED,BIOLOID_LED,address,length)) - { - byte_value=data[BIOLOID_LED-address]; - if(byte_value&0x01) - gpio_set_led(NORTH_LED); - else - gpio_clear_led(NORTH_LED); - if(byte_value&0x02) - gpio_set_led(SOUTH_LED); - else - gpio_clear_led(SOUTH_LED); - if(byte_value&0x04) - gpio_set_led(EAST_LED); - else - gpio_clear_led(EAST_LED); - if(byte_value&0x08) - gpio_set_led(WEST_LED); - else - gpio_clear_led(WEST_LED); - } - if(ram_in_range(BIOLOID_MM_PERIOD,BIOLOID_MM_PERIOD+1,address,length)) - { - word_value=data[BIOLOID_MM_PERIOD-address]+(data[BIOLOID_MM_PERIOD+1-address]<<8); - action_set_period(word_value); - word_value=(word_value*1000000)>>16; - manager_set_period(word_value); - } - for(i=BIOLOID_MM_MODULE_EN0,j=0;i<=BIOLOID_MM_MODULE_EN15;i++,j+=2) - { - do_op=0x01; - if(ram_in_range(i,i,address,length)) - { - byte_value=data[i-address]; - if(byte_value&0x80) manager_enable_servo(j); - else manager_disable_servo(j); - manager_set_module(j,(byte_value&0x70)>>4); - if(byte_value&0x08) manager_enable_servo(j+1); - else manager_disable_servo(j+1); - manager_set_module(j+1,byte_value&0x07); - } - } - if(do_op) - { - do_op=0x00; - manager_disable_servos(); - } - if(ram_in_range(BIOLOID_IMU_CONTROL,BIOLOID_IMU_CONTROL,address,length)) - { - if(data[BIOLOID_IMU_CONTROL-address]&0x01) - imu_start(); - else - imu_stop(); - } - if(ram_in_range(BIOLOID_MM_CONTROL,BIOLOID_MM_CONTROL,address,length)) - { - if(data[BIOLOID_MM_CONTROL-address]&0x01) - manager_enable(); - else - manager_disable(); - } - if(ram_in_range(BIOLOID_ACTION_CONTROL,BIOLOID_ACTION_CONTROL,address,length)) - { - if(data[BIOLOID_ACTION_CONTROL-address]&0x01) - action_start_page(); - if(data[BIOLOID_ACTION_CONTROL-address]&0x02) - action_stop_page(); - } - if(ram_in_range(BIOLOID_ACTION_PAGE,BIOLOID_ACTION_PAGE,address,length))// load the page identifier - action_load_page(data[BIOLOID_ACTION_PAGE-address]); - // write eeprom - for(i=address,j=0;i<LAST_EEPROM_OFFSET && i<(address+length);i++,j++) - EE_WriteVariable(i,data[j]); - // write operation - error=ram_write_table(address,length,data); - // post-write operation - - return error; -} +#include "comm.h" int32_t main(void) { - uint8_t inst_packet[1024]; - uint8_t status_packet[1024]; - uint8_t data[1024],error,length; uint16_t eeprom_data,i,num_errors=0; uint16_t action_period,mm_period; TPage page; @@ -136,8 +30,8 @@ int32_t main(void) /* initialize the gpio */ gpio_init(); /* initialize the dynamixel master interface */ - dyn_master_init(); - dyn_master_set_timeout(20); +// dyn_master_init(); +// dyn_master_set_timeout(20); /* initialize the dynamixel slave interface*/ dyn_slave_init(); EE_ReadVariable(DEVICE_ID_OFFSET,&eeprom_data); @@ -147,18 +41,21 @@ int32_t main(void) EE_ReadVariable(RETURN_LEVEL_OFFSET,&eeprom_data); dyn_slave_set_return_level((uint8_t)eeprom_data); /* initialize the IMU */ - imu_init(); +// imu_init(); // initialize the Analog to digital converter // adc_init(); // initialize motion manager - EE_ReadVariable(MM_PERIOD_OFFSET,&eeprom_data); - action_period=eeprom_data&0x00FF; - EE_ReadVariable(MM_PERIOD_OFFSET+1,&eeprom_data); - action_period+=((eeprom_data&0x00FF)<<8); - mm_period=(action_period*1000000)>>16; - manager_init(mm_period); +// EE_ReadVariable(MM_PERIOD_OFFSET,&eeprom_data); +// action_period=eeprom_data&0x00FF; +// EE_ReadVariable(MM_PERIOD_OFFSET+1,&eeprom_data); +// action_period+=((eeprom_data&0x00FF)<<8); +// mm_period=(action_period*1000000)>>16; +// manager_init(mm_period); // initialize the action module - action_init(action_period); +// action_init(action_period); + comm_init(); + + comm_start(); gpio_blink_led(NORTH_LED,1000); @@ -171,65 +68,6 @@ int32_t main(void) if(num_errors==0) gpio_set_led(SOUTH_LED); - while(1) /* main function does not return */ - { - if(dyn_slave_is_packet_ready())// check if a new instruction packet has been received - { - dyn_slave_get_inst_packet(inst_packet);// get the received packet - // check the packet checksum - if(dyn_check_checksum(inst_packet)==0xFF)// the incomming packet is okay - { - // check address - if(dyn_get_id(inst_packet)==dyn_slave_get_address())// the packet is addressed to this device - { - // process the packet - switch(dyn_get_instruction(inst_packet)) - { - case DYN_PING: dyn_slave_send_status_packet(DYN_NO_ERROR,0,data); - break; - case DYN_READ: error=read_operation(dyn_get_read_address(inst_packet),dyn_get_read_length(inst_packet),data); - if(dyn_slave_get_return_level()!=0) - { - if(error==RAM_SUCCESS) - dyn_slave_send_status_packet(DYN_NO_ERROR,dyn_get_read_length(inst_packet),data); - else - dyn_slave_send_status_packet(DYN_INST_ERROR,0,data); - } - break; - case DYN_WRITE: length=dyn_get_write_data(inst_packet,data); - if(length!=DYN_BAD_FORMAT) - error=write_operation(dyn_get_write_address(inst_packet),length,data); - if(dyn_slave_get_return_level()==2) - { - if(error==RAM_SUCCESS || length==DYN_BAD_FORMAT) - dyn_slave_send_status_packet(DYN_NO_ERROR,0,data); - else - dyn_slave_send_status_packet(DYN_INST_ERROR,0,data); - } - - break; - default: - break; - } - } - else// the packet is addressed to another device - { - // send the incomming packet to the dynamixel bus - if(dyn_master_resend_inst_packet(inst_packet,status_packet)==DYN_NO_ERROR) - { - // send the answer back to the computer - dyn_slave_resend_status_packet(status_packet); - } - else - dyn_slave_reset();// prepare the dynamixel master to accept data - } - } - else - { - // send a checksum error answer - dyn_slave_send_status_packet(DYN_CHECKSUM_ERROR,0,0x00); - } - } - } + while(1); } diff --git a/src/comm.c b/src/comm.c new file mode 100644 index 0000000000000000000000000000000000000000..f96d8c08768ae007437a032ade8d9f9f8a8d0247 --- /dev/null +++ b/src/comm.c @@ -0,0 +1,287 @@ +#include "comm.h" +#include "gpio.h" +#include "ram.h" +#include "motion_manager.h" +#include "action.h" +#include "dynamixel_slave_uart_dma.h" +#include "dynamixel_master_uart_dma.h" +#include "adc_dma.h" + +#define COMM_TIMER TIM7 +#define COMM_TIMER_IRQn TIM7_IRQn +#define COMM_TIMER_IRQHandler TIM7_IRQHandler +#define COMM_TIMER_CLK RCC_APB1Periph_TIM7 + +// private variables +uint8_t inst_packet[MAX_DATA_LENGTH]; +uint8_t status_packet[MAX_DATA_LENGTH]; +uint8_t data[MAX_DATA_LENGTH]; +// registered write operation variables +uint8_t reg_data[MAX_DATA_LENGTH]; +uint8_t reg_address,reg_length,reg_op; + +// private functions +uint8_t read_operation(uint8_t address, uint8_t length, uint8_t *data) +{ + uint8_t error; + + // pre-read operation + // read operation + error=ram_read_table(address,length,data); + // post-read operation + if(ram_in_range(BIOLOID_PUSHBUTTON,BIOLOID_PUSHBUTTON,address,length)) + ram_data[BIOLOID_PUSHBUTTON]=0x00; + + return error; +} + +uint8_t write_operation(uint8_t address,uint8_t length, uint8_t *data) +{ + uint8_t error=RAM_SUCCESS,byte_value,i,j,do_op=0x00,module; + uint16_t word_value; + + // pre-write operation + if(ram_in_range(BIOLOID_DXL_POWER,BIOLOID_DXL_POWER,address,length)) + { + if(data[BIOLOID_DXL_POWER-address]&0x01) dyn_master_enable_power(); + else dyn_master_disable_power(); + } + if(ram_in_range(BIOLOID_LED,BIOLOID_LED,address,length)) + { + byte_value=data[BIOLOID_LED-address]; + if(byte_value&0x01) + gpio_set_led(NORTH_LED); + else + gpio_clear_led(NORTH_LED); + if(byte_value&0x02) + gpio_set_led(SOUTH_LED); + else + gpio_clear_led(SOUTH_LED); + if(byte_value&0x04) + gpio_set_led(EAST_LED); + else + gpio_clear_led(EAST_LED); + if(byte_value&0x08) + gpio_set_led(WEST_LED); + else + gpio_clear_led(WEST_LED); + } + if(ram_in_range(BIOLOID_MM_PERIOD_L,BIOLOID_MM_PERIOD_H,address,length)) + { + word_value=data[BIOLOID_MM_PERIOD_L-address]+(data[BIOLOID_MM_PERIOD_H-address]<<8); + manager_set_period(word_value); + } + for(i=BIOLOID_MM_MODULE_EN0,j=0;i<=BIOLOID_MM_MODULE_EN15;i++,j+=2) + { + do_op=0x01; + if(ram_in_range(i,i,address,length)) + { + byte_value=data[i-address]; + if(byte_value&0x80) manager_enable_servo(j); + else manager_disable_servo(j); + module=(byte_value&0x70)>>4; + manager_set_module(j,module); + if(byte_value&0x08) manager_enable_servo(j+1); + else manager_disable_servo(j+1); + module=byte_value&0x07; + manager_set_module(j+1,module); + } + } + if(do_op) + { + do_op=0x00; + manager_disable_servos(); + } + if(ram_in_range(BIOLOID_MM_CONTROL,BIOLOID_MM_CONTROL,address,length)) + { + if(data[BIOLOID_MM_CONTROL-address]&0x01) + manager_enable(); + else + manager_disable(); + } +/* if(ram_in_range(BIOLOID_MM_KNEE_GAIN_L,BIOLOID_MM_KNEE_GAIN_L,address,length)) + manager_set_knee_gain(data[BIOLOID_MM_KNEE_GAIN_L-address]); + if(ram_in_range(BIOLOID_MM_KNEE_GAIN_R,BIOLOID_MM_KNEE_GAIN_R,address,length)) + manager_set_knee_gain(data[BIOLOID_MM_KNEE_GAIN_R-address]); + if(ram_in_range(BIOLOID_MM_ANKLE_PITCH_GAIN_L,BIOLOID_MM_ANKLE_PITCH_GAIN_L,address,length)) + manager_set_ankle_pitch_gain(data[BIOLOID_MM_ANKLE_PITCH_GAIN_L,address]); + if(ram_in_range(BIOLOID_MM_ANKLE_PITCH_GAIN_R,BIOLOID_MM_ANKLE_PITCH_GAIN_R,address,length)) + manager_set_ankle_pitch_gain(data[BIOLOID_MM_ANKLE_PITCH_GAIN_R,address]); + if(ram_in_range(BIOLOID_MM_HIP_ROLL_GAIN_L,BIOLOID_MM_HIP_ROLL_GAIN_L,address,length)) + manager_set_hip_roll_gain(data[BIOLOID_MM_ROLL_GAIN_L-address]); + if(ram_in_range(BIOLOID_MM_HIP_ROLL_GAIN_R,BIOLOID_MM_HIP_ROLL_GAIN_R,address,length)) + manager_set_hip_roll_gain(data[BIOLOID_MM_ROLL_GAIN_R-address]); + if(ram_in_range(BIOLOID_MM_ANKLE_ROLL_GAIN_L,BIOLOID_MM_ANKLE_ROLL_GAIN_L,address,length)) + manager_set_ankle_roll_gain(data[BIOLOID_MM_CONTROL_L-address]); + if(ram_in_range(BIOLOID_MM_ANKLE_ROLL_GAIN_R,BIOLOID_MM_ANKLE_ROLL_GAIN_R,address,length)) + manager_set_ankle_roll_gain(data[BIOLOID_MM_CONTROL_R-address]);*/ + if(ram_in_range(BIOLOID_ACTION_CONTROL,BIOLOID_ACTION_CONTROL,address,length)) + { + if(data[BIOLOID_ACTION_CONTROL-address]&0x01) + action_start_page(); + if(data[BIOLOID_ACTION_CONTROL-address]&0x02) + action_stop_page(); + } + if(ram_in_range(BIOLOID_ACTION_PAGE,BIOLOID_ACTION_PAGE,address,length))// load the page identifier + action_load_page(data[BIOLOID_ACTION_PAGE-address]); +/* if(ram_in_range(BIOLOID_IMU_CONTROL,BIOLOID_IMU_CONTROL,address,length)) + { + if(data[BIOLOID_IMU_CONTROL-address]&0x01) + imu_start(); + else + imu_stop(); + if(data[BIOLOID_IMU_CONTROL-address]&0x02) + imu_start_gyro_cal(); + }*/ + // write eeprom + for(i=address,j=0;i<LAST_EEPROM_OFFSET && i<(address+length);i++,j++) + EE_WriteVariable(i,data[j]); + // write operation + // error=ram_write_table(address,length,data); + // post-write operation + + return error; +} + +// interrupt handlers +void COMM_TIMER_IRQHandler(void) +{ + uint8_t error,length,prev_id,id; + + TIM_ClearITPendingBit(COMM_TIMER,TIM_IT_Update); + if(dyn_slave_is_packet_ready())// check if a new instruction packet has been received + { + dyn_slave_get_inst_packet(inst_packet);// get the received packet + // check address + id=dyn_get_id(inst_packet); + if(id==dyn_slave_get_address() || id==DYN_BROADCAST_ID)// the packet is addressed to this device or it is a broadcast + { + // check the packet checksum + if(dyn_check_checksum(inst_packet)==0xFF)// the incomming packet is okay + { + // process the packet + switch(dyn_get_instruction(inst_packet)) + { + case DYN_PING: if(id!=DYN_BROADCAST_ID) + dyn_slave_send_status_packet(DYN_NO_ERROR,0,data); + break; + case DYN_READ: error=read_operation(dyn_get_read_address(inst_packet),dyn_get_read_length(inst_packet),data); + if(dyn_slave_get_return_level()!=0 && id!=DYN_BROADCAST_ID) + { + if(error==RAM_SUCCESS) + dyn_slave_send_status_packet(DYN_NO_ERROR,dyn_get_read_length(inst_packet),data); + else + dyn_slave_send_status_packet(DYN_INST_ERROR,0,data); + } + break; + case DYN_WRITE: length=dyn_get_write_data(inst_packet,data); + error=write_operation(dyn_get_write_address(inst_packet),length,data); + if(dyn_slave_get_return_level()==2 && id!=DYN_BROADCAST_ID) + { + if(error==RAM_SUCCESS) + dyn_slave_send_status_packet(DYN_NO_ERROR,0,data); + else + dyn_slave_send_status_packet(DYN_INST_ERROR,0,data); + } + break; + case DYN_REG_WRITE: reg_length=dyn_get_reg_write_data(inst_packet,reg_data); + reg_address=dyn_get_reg_write_address(inst_packet); + reg_op=0x01;// signal there is a registered operation pending + if(dyn_slave_get_return_level()==2 && id!=DYN_BROADCAST_ID) + dyn_slave_send_status_packet(DYN_NO_ERROR,0,data); + break; + case DYN_ACTION: if(reg_op) + { + error=write_operation(reg_address,reg_length,reg_data); + reg_op=0x00; + } + break; + case DYN_RESET: + break; + case DYN_SYNC_READ: dyn_slave_send_status_packet(DYN_INST_ERROR,0,data); + break; + case DYN_SYNC_WRITE: if(dyn_sync_write_id_present(inst_packet,dyn_slave_get_address()))// the device is addressed + { + length=dyn_get_sync_write_data(inst_packet,dyn_slave_get_address(),data); + error=write_operation(dyn_get_sync_write_address(inst_packet),length,data); + } + break; + case DYN_BULK_READ: if(dyn_bulk_read_id_present(inst_packet,dyn_slave_get_address(),&prev_id)) + { + length=dyn_get_bulk_read_length(inst_packet,dyn_slave_get_address()); + error=read_operation(dyn_get_bulk_read_address(inst_packet,dyn_slave_get_address()),length,data); + if(prev_id==0xFF)// first device in the bulk read sequence + { + if(error==RAM_SUCCESS) + dyn_slave_send_status_packet(DYN_NO_ERROR,length,data); + else + dyn_slave_send_status_packet(DYN_INST_ERROR,0,data); + } + else// wait for the previous device in the sequence to send its data + { + do{ + while(!dyn_slave_is_packet_ready());// wait until a new packet is received + dyn_slave_get_inst_packet(inst_packet); + }while(dyn_get_id(inst_packet)!=prev_id); + if(error==RAM_SUCCESS) + dyn_slave_send_status_packet(DYN_NO_ERROR,length,data); + else + dyn_slave_send_status_packet(DYN_INST_ERROR,0,data); + } + } + break; + case DYN_BULK_WRITE: dyn_slave_send_status_packet(DYN_INST_ERROR,0,data); + break; + default: + break; + } + } + else + { + // send a checksum error answer + if(dyn_get_id(inst_packet)!=DYN_BROADCAST_ID) + dyn_slave_send_status_packet(DYN_CHECKSUM_ERROR,0,0x00); + } + } + else// the packet is addressed to another device + { + // send the incomming packet to the dynamixel bus + if(dyn_master_resend_inst_packet(inst_packet,status_packet)!=DYN_TIMEOUT) + { + // send the answer back to the computer + dyn_slave_resend_status_packet(status_packet); + } + } + } +} + +// public functions +void comm_init(void) +{ + TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; + NVIC_InitTypeDef NVIC_InitStructure; + + RCC_APB1PeriphClockCmd(COMM_TIMER_CLK,ENABLE); + + TIM_TimeBaseStructure.TIM_Period = 1000; + TIM_TimeBaseStructure.TIM_Prescaler = 84; + TIM_TimeBaseStructure.TIM_ClockDivision = 0; + TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseInit(COMM_TIMER,&TIM_TimeBaseStructure); + + NVIC_InitStructure.NVIC_IRQChannel = COMM_TIMER_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + + /* initialize variables */ + reg_op=0x00; +} + +void comm_start(void) +{ + TIM_Cmd(COMM_TIMER, ENABLE); + TIM_ITConfig(COMM_TIMER, TIM_IT_Update, ENABLE); +} + diff --git a/src/dynamixel_master_uart_dma.c b/src/dynamixel_master_uart_dma.c index e5f0e48c97e7cfc7185feac63dd6c0a5c0296031..b1f98b08cc97c2b94b5d33894f3aa50ee1ce51f4 100755 --- a/src/dynamixel_master_uart_dma.c +++ b/src/dynamixel_master_uart_dma.c @@ -1,6 +1,6 @@ #include "dynamixel_master_uart_dma.h" +#include "motion_manager.h" #include "time.h" -#include "gpio.h" #define USART USART2 #define USART_CLK RCC_APB1Periph_USART2 @@ -65,10 +65,10 @@ #define MAX_BUFFER_LEN 1024 // private variables +uint8_t dyn_master_version; uint16_t dyn_master_timeout;// answer reception timeout // input buffer uint8_t dyn_master_rx_buffer[MAX_BUFFER_LEN]; -volatile uint8_t dyn_master_receiving_header; // output buffer uint8_t dyn_master_tx_buffer[MAX_BUFFER_LEN]; // instruction packet ready flag @@ -79,6 +79,9 @@ volatile uint8_t dyn_master_sending_packet; uint8_t dyn_master_no_answer; // power enabled variable uint8_t dyn_master_power_enabled; +// number of packets to receive +uint8_t dyn_master_num_read_packets; +uint8_t dyn_master_packet_length; // DMA initialization data structures DMA_InitTypeDef DMA_TX_InitStructure; DMA_InitTypeDef DMA_RX_InitStructure; @@ -86,42 +89,93 @@ DMA_InitTypeDef DMA_RX_InitStructure; // private functions void dyn_master_reset(void) { - DMA_ITConfig(USART_RX_DMA_STREAM,DMA_IT_TC,DISABLE); + /* Reset reception */ USART_DMACmd(USART, USART_DMAReq_Rx, DISABLE); DMA_Cmd(USART_RX_DMA_STREAM,DISABLE); /* wait until the transaction ends */ - while(DMA_GetCmdStatus(USART_RX_DMA_STREAM)==ENABLE); DMA_ClearFlag(USART_RX_DMA_STREAM,USART_RX_DMA_FLAG_TCIF); DMA_ClearITPendingBit(USART_RX_DMA_STREAM,USART_RX_DMA_FLAG_TCIF); - dyn_master_receiving_header=0x01; + /* clear any pending data */ + USART_ReceiveData(USART); + /* Reset transmission */ + USART_DMACmd(USART, USART_DMAReq_Tx, DISABLE); + DMA_Cmd(USART_TX_DMA_STREAM,DISABLE); + DMA_ClearFlag(USART_TX_DMA_STREAM,USART_TX_DMA_FLAG_TCIF); + DMA_ClearITPendingBit(USART_TX_DMA_STREAM,USART_TX_DMA_FLAG_TCIF); + USART_ITConfig(USART, USART_IT_TC, DISABLE); + /* Reset variables */ dyn_master_packet_ready=0x00; + dyn_master_sending_packet=0x00; } -void dyn_master_send(void) +uint8_t dyn_master_wait_sending(void) { + uint16_t timeout_left=dyn_master_timeout*1000; + + while(dyn_master_sending_packet) + { + delay_us(100); + timeout_left-=100; + if(timeout_left<=0) + { + dyn_master_reset(); + return DYN_TIMEOUT; + } + } + + return DYN_SUCCESS; +} + +uint8_t dyn_master_send(void) +{ + uint8_t error; + + dyn_master_version=1; // wait until any previous transmission ends - while(dyn_master_sending_packet); + if((error=dyn_master_wait_sending())!=DYN_SUCCESS) + return error; // set the DMA transfer DMA_SetCurrDataCounter(USART_TX_DMA_STREAM,dyn_get_length(dyn_master_tx_buffer)+4); DMA_Cmd(USART_TX_DMA_STREAM,ENABLE); USART_ClearFlag(USART,USART_FLAG_TC); + USART_ClearITPendingBit(USART,USART_FLAG_TC); USART_DMACmd(USART, USART_DMAReq_Tx, ENABLE); dyn_master_sending_packet=0x01; + return error; + +} + +uint8_t dyn2_master_send(void) +{ + uint8_t error; + + dyn_master_version=2; + // wait until any previous transmission ends + if((error=dyn_master_wait_sending())!=DYN_SUCCESS) + return error; + // set the DMA transfer + DMA_SetCurrDataCounter(USART_TX_DMA_STREAM,dyn2_get_length(dyn_master_tx_buffer)+7); + DMA_Cmd(USART_TX_DMA_STREAM,ENABLE); + USART_ClearFlag(USART,USART_FLAG_TC); + USART_ClearITPendingBit(USART,USART_FLAG_TC); + USART_DMACmd(USART, USART_DMAReq_Tx, ENABLE); + dyn_master_sending_packet=0x01; + return error; } uint8_t dyn_master_receive(void) { - int16_t timeout_left=dyn_master_timeout; + uint16_t timeout_left=dyn_master_timeout*1000; // wait for the status packet while(!dyn_master_packet_ready) { - delay_ms(1); - timeout_left-=1; + delay_us(100); + timeout_left-=100; if(timeout_left<=0) { dyn_master_reset(); - return DYN_TIMEOUT; + return DYN_TIMEOUT; } } dyn_master_packet_ready=0x00; @@ -129,7 +183,36 @@ uint8_t dyn_master_receive(void) if(dyn_check_checksum(dyn_master_rx_buffer)==0xFF) return dyn_get_status_error(dyn_master_rx_buffer); else + { + dyn_master_reset(); return DYN_CHECKSUM_ERROR; + } +} + +uint8_t dyn2_master_receive(void) +{ + uint16_t timeout_left=dyn_master_timeout*1000; + + // wait for the status packet + while(!dyn_master_packet_ready) + { + delay_us(100); + timeout_left-=100; + if(timeout_left<=0) + { + dyn_master_reset(); + return DYN_TIMEOUT; + } + } + dyn_master_packet_ready=0x00; + // check the input packet checksum + if(dyn2_check_checksum(dyn_master_rx_buffer)==0x01) + return dyn2_get_status_error(dyn_master_rx_buffer); + else + { + dyn_master_reset(); + return DYN_CHECKSUM_ERROR; + } } void dyn_master_enable_tx(void) @@ -148,80 +231,169 @@ uint8_t dyn_master_read(uint8_t id,uint8_t address,uint8_t length,uint8_t *data) { uint8_t error; + /* generate the read packet */ + dyn_init_read_packet(dyn_master_tx_buffer,id,address,length); + dyn_master_num_read_packets=0x01; + // enable transmission + dyn_master_enable_tx(); + // send the data + if((error=dyn_master_send())!=DYN_SUCCESS) + { + dyn_master_enable_rx(); + return error; + } // wait for the transmission to end - while(dyn_master_sending_packet); - // generate the read packet for the desired device - dyn_init_instruction_packet(dyn_master_tx_buffer); - // set the ping instruction - dyn_set_instruction(dyn_master_tx_buffer,DYN_READ); - // set the device id - if((error=dyn_set_id(dyn_master_tx_buffer,id))==DYN_SUCCESS) - { - // set the length to read - dyn_set_read_length(dyn_master_tx_buffer,length); - // sert the start address to start reading - dyn_set_read_address(dyn_master_tx_buffer,address); - // set the checksum - dyn_set_checksum(dyn_master_tx_buffer); - // enable transmission - dyn_master_enable_tx(); - // send the data - dyn_master_send(); - // wait for the transmission to end - while(dyn_master_sending_packet); + if((error=dyn_master_wait_sending())!=DYN_SUCCESS) + { dyn_master_enable_rx(); - // wait for the replay within the given timeout - error=dyn_master_receive(); - if(error==DYN_NO_ERROR) - dyn_get_status_data(dyn_master_rx_buffer,data);// read the data from the status packet - else - dyn_master_reset(); return error; } + dyn_master_enable_rx(); + // wait for the replay within the given timeout + error=dyn_master_receive(); + if(error==DYN_NO_ERROR) + dyn_get_read_status_data(dyn_master_rx_buffer,data);// read the data from the status packet else + dyn_master_reset(); + return error; +} + +uint8_t dyn2_master_read(uint8_t id,uint16_t address,uint16_t length,uint8_t *data) +{ + uint8_t error; + + /* generate the read packet */ + dyn2_init_read_packet(dyn_master_tx_buffer,id,address,length); + dyn_master_num_read_packets=0x01; + // enable transmission + dyn_master_enable_tx(); + // send the data + if((error=dyn2_master_send())!=DYN_SUCCESS) + { + dyn_master_enable_rx(); return error; + } + // wait for the transmission to end + if((error=dyn_master_wait_sending())!=DYN_SUCCESS) + { + dyn_master_enable_rx(); + return error; + } + dyn_master_enable_rx(); + // wait for the replay within the given timeout + error=dyn2_master_receive(); + if(error==DYN_NO_ERROR) + dyn2_get_read_status_data(dyn_master_rx_buffer,data);// read the data from the status packet + else + dyn_master_reset(); + return error; } uint8_t dyn_master_write(uint8_t id, uint8_t address, uint8_t length, uint8_t *data) { uint8_t error; - + + // generate the read packet for the desired device + dyn_init_write_packet(dyn_master_tx_buffer,id,address,length,data); + dyn_master_num_read_packets=0x01; + // enable transmission + dyn_master_enable_tx(); + // send the data + if((error=dyn_master_send())!=DYN_SUCCESS) + { + dyn_master_enable_rx(); + return error; + } // wait for the transmission to end - while(dyn_master_sending_packet); + if((error=dyn_master_wait_sending())!=DYN_SUCCESS) + { + dyn_master_enable_rx(); + return error; + } + dyn_master_enable_rx(); + // wait for the replay within the given timeout + error=dyn_master_receive(); + if(error!=DYN_NO_ERROR) + dyn_master_reset(); + return error; +} + +uint8_t dyn2_master_write(uint8_t id, uint16_t address, uint16_t length, uint8_t *data) +{ + uint8_t error; + // generate the read packet for the desired device - dyn_init_instruction_packet(dyn_master_tx_buffer); - // set the ping instruction - dyn_set_instruction(dyn_master_tx_buffer,DYN_WRITE); - // set the device id - if((error=dyn_set_id(dyn_master_tx_buffer,id))==DYN_SUCCESS) - { - // sert the start address to start reading - dyn_set_read_address(dyn_master_tx_buffer,address); - // set the data to write and its length - dyn_set_write_data(dyn_master_tx_buffer,length,data); - // set the checksum - dyn_set_checksum(dyn_master_tx_buffer); - // enable transmission - dyn_master_enable_tx(); - // send the data - dyn_master_send(); - // wait for the transmission to end - while(dyn_master_sending_packet); + dyn2_init_write_packet(dyn_master_tx_buffer,id,address,length,data); + dyn_master_num_read_packets=0x01; + // enable transmission + dyn_master_enable_tx(); + // send the data + if((error=dyn2_master_send())!=DYN_SUCCESS) + { dyn_master_enable_rx(); - // wait for the replay within the given timeout - error=dyn_master_receive(); - if(error!=DYN_NO_ERROR) - dyn_master_reset(); return error; - } - else + } + // wait for the transmission to end + if((error=dyn_master_wait_sending())!=DYN_SUCCESS) + { + dyn_master_enable_rx(); return error; + } + dyn_master_enable_rx(); + // wait for the replay within the given timeout + error=dyn2_master_receive(); + if(error!=DYN_NO_ERROR) + dyn_master_reset(); + return error; } // interrupt handlers void USART_IRQHandler(void) { - if(USART_GetITStatus(USART, USART_IT_TC) != RESET) + static uint8_t num_bytes=0; + uint8_t data; + + if(USART_GetITStatus(USART, USART_IT_RXNE) != RESET) + { + USART_ClearFlag(USART,USART_FLAG_RXNE); + data=USART_ReceiveData(USART); + switch(num_bytes) + { + case 0: if(data==0xFF) + { + dyn_master_rx_buffer[num_bytes]=data; + num_bytes++; + } + break; + case 1: if(data==0xFF) + { + dyn_master_rx_buffer[num_bytes]=data; + num_bytes++; + } + else num_bytes--; + break; + case 2: if(data!=0xFF) + { + dyn_master_rx_buffer[num_bytes]=data; + num_bytes++; + } + break; + case 3: dyn_master_rx_buffer[num_bytes]=data; + num_bytes=0; + /* disable USART RX interrupts */ + USART_ITConfig(USART,USART_IT_RXNE,DISABLE); + /* enable DMA RX */ + DMA_RX_InitStructure.DMA_BufferSize = data; + DMA_RX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&dyn_master_rx_buffer[dyn_master_packet_length+4]; + dyn_master_packet_length+=data+4; + DMA_Init(USART_RX_DMA_STREAM,&DMA_RX_InitStructure); + DMA_Cmd(USART_RX_DMA_STREAM,ENABLE); + USART_DMACmd(USART, USART_DMAReq_Rx, ENABLE); + break; + default: break; + } + } + else if(USART_GetITStatus(USART, USART_IT_TC) != RESET) { USART_ClearFlag(USART,USART_FLAG_TC); USART_ITConfig(USART, USART_IT_TC, DISABLE); @@ -230,44 +402,37 @@ void USART_IRQHandler(void) dyn_master_no_answer=0x00; else { - // set up the DMA RX transaction - DMA_RX_InitStructure.DMA_BufferSize = 4; - DMA_RX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)dyn_master_rx_buffer; - DMA_Init(USART_RX_DMA_STREAM,&DMA_RX_InitStructure); - DMA_ITConfig(USART_RX_DMA_STREAM,DMA_IT_TC,ENABLE); - DMA_Cmd(USART_RX_DMA_STREAM,ENABLE); - USART_DMACmd(USART, USART_DMAReq_Rx, ENABLE); - dyn_master_receiving_header=0x01; + /* enable RX interrupts */ + USART_ITConfig(USART, USART_IT_RXNE, ENABLE); } } } void USART_DMA_TX_IRQHandler(void) { + DMA_Cmd(USART_TX_DMA_STREAM,DISABLE); DMA_ClearFlag(USART_TX_DMA_STREAM,USART_TX_DMA_FLAG_TCIF); DMA_ClearITPendingBit(USART_TX_DMA_STREAM,USART_TX_DMA_FLAG_TCIF); + USART_DMACmd(USART, USART_DMAReq_Tx, DISABLE); USART_ITConfig(USART, USART_IT_TC, ENABLE); } void USART_DMA_RX_IRQHandler(void) { - if(dyn_master_receiving_header==0x01) + DMA_Cmd(USART_RX_DMA_STREAM,DISABLE); + DMA_ClearFlag(USART_RX_DMA_STREAM,USART_RX_DMA_FLAG_TCIF); + DMA_ClearITPendingBit(USART_RX_DMA_STREAM,USART_RX_DMA_FLAG_TCIF); + USART_DMACmd(USART, USART_DMAReq_Rx, DISABLE); + dyn_master_num_read_packets--; + if(dyn_master_num_read_packets==0x00) { - DMA_ClearFlag(USART_RX_DMA_STREAM,USART_RX_DMA_FLAG_TCIF); - DMA_ClearITPendingBit(USART_RX_DMA_STREAM,USART_RX_DMA_FLAG_TCIF); - DMA_RX_InitStructure.DMA_BufferSize = dyn_get_length(dyn_master_rx_buffer); - DMA_RX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&dyn_master_rx_buffer[4]; - DMA_Init(USART_RX_DMA_STREAM,&DMA_RX_InitStructure); - DMA_Cmd(USART_RX_DMA_STREAM,ENABLE); - USART_DMACmd(USART, USART_DMAReq_Rx, ENABLE); - dyn_master_receiving_header=0x00; + dyn_master_packet_length=0x00; + dyn_master_packet_ready=0x01; } else { - DMA_ClearFlag(USART_RX_DMA_STREAM,USART_RX_DMA_FLAG_TCIF); - DMA_ClearITPendingBit(USART_RX_DMA_STREAM,USART_RX_DMA_FLAG_TCIF); - DMA_ITConfig(USART_RX_DMA_STREAM,DMA_IT_TC,DISABLE); - dyn_master_packet_ready=0x01; + /* enable RX interrupts */ + USART_ITConfig(USART, USART_IT_RXNE, ENABLE); } } @@ -326,8 +491,10 @@ void dyn_master_init(void) // initialize the flags dyn_master_packet_ready=0x00; dyn_master_sending_packet=0x00; - dyn_master_receiving_header=0x01; dyn_master_no_answer=0x00; + dyn_master_num_read_packets=0x00; + dyn_master_packet_length=0x00; + dyn_master_version=1; USART_DeInit(USART); USART_StructInit(&USART_InitStructure); @@ -341,11 +508,39 @@ void dyn_master_init(void) USART_Init(USART, &USART_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = USART_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); - USART_ITConfig(USART, USART_IT_RXNE | USART_IT_ORE | USART_IT_TXE | USART_IT_CTS | USART_IT_LBD | USART_IT_IDLE | USART_IT_PE | USART_IT_ERR | USART_IT_TC, DISABLE); + USART_ITConfig(USART, USART_IT_RXNE | + USART_IT_ORE | + USART_IT_TXE | + USART_IT_CTS | + USART_IT_LBD | + USART_IT_IDLE | + USART_IT_PE | + USART_IT_ERR | + USART_IT_TC, DISABLE); + + /* Clear all USART interrupt flags */ + USART_ClearFlag(USART,USART_FLAG_RXNE | + USART_FLAG_ORE | + USART_FLAG_TXE | + USART_FLAG_CTS | + USART_FLAG_LBD | + USART_FLAG_IDLE | + USART_FLAG_PE | + USART_FLAG_TC); + + /* Clear all USART interrupt pending bits */ + USART_ClearITPendingBit(USART, USART_FLAG_RXNE | + USART_FLAG_ORE | + USART_FLAG_TXE | + USART_FLAG_CTS | + USART_FLAG_LBD | + USART_FLAG_IDLE | + USART_FLAG_PE | + USART_FLAG_TC); // configure the DMA channels /* Configure TX DMA */ @@ -368,8 +563,8 @@ void dyn_master_init(void) DMA_Init(USART_TX_DMA_STREAM,&DMA_TX_InitStructure); /* initialize DMA interrupts */ NVIC_InitStructure.NVIC_IRQChannel = USART_DMA_TX_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); DMA_ITConfig(USART_TX_DMA_STREAM,DMA_IT_TC,ENABLE); @@ -377,7 +572,6 @@ void dyn_master_init(void) /* Configure RX DMA */ DMA_DeInit(USART_RX_DMA_STREAM); - DMA_RX_InitStructure.DMA_BufferSize = 4;// transfer the first 3 bytes DMA_RX_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_RX_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; DMA_RX_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; @@ -391,15 +585,16 @@ void dyn_master_init(void) DMA_RX_InitStructure.DMA_Priority = DMA_Priority_High; DMA_RX_InitStructure.DMA_Channel = USART_RX_DMA_CHANNEL; DMA_RX_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; - DMA_RX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)dyn_master_rx_buffer; + DMA_RX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&dyn_master_rx_buffer[4]; DMA_Init(USART_RX_DMA_STREAM,&DMA_RX_InitStructure); /* initialize DMA interrupts */ NVIC_InitStructure.NVIC_IRQChannel = USART_DMA_RX_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); - DMA_ITConfig(USART_RX_DMA_STREAM,DMA_IT_TC | DMA_IT_HT | DMA_IT_TE | DMA_IT_FE | DMA_IT_DME,DISABLE); + DMA_ITConfig(USART_RX_DMA_STREAM,DMA_IT_TC,ENABLE); + DMA_ITConfig(USART_RX_DMA_STREAM,DMA_IT_HT | DMA_IT_TE | DMA_IT_FE | DMA_IT_DME,DISABLE); /* Enable the USART2 */ USART_Cmd(USART, ENABLE); @@ -415,11 +610,6 @@ void dyn_master_init(void) dyn_master_disable_power(); } -void dyn_master_flush(void) -{ - // flush only the reception buffer to avoid interrupting a sync_write command -} - void dyn_master_set_timeout(uint16_t timeout_ms) { // save the desired timeout value @@ -430,6 +620,8 @@ void dyn_master_scan(uint8_t *num,uint8_t *ids) { uint8_t i; + for(i=0;i<MANAGER_MAX_NUM_SERVOS;i++) + ids[0]=0; *num=0; for(i=0;i<254;i++) { @@ -441,6 +633,23 @@ void dyn_master_scan(uint8_t *num,uint8_t *ids) } } +void dyn2_master_scan(uint8_t *num,uint8_t *ids) +{ + uint8_t i; + + for(i=0;i<MANAGER_MAX_NUM_SERVOS;i++) + ids[0]=0; + *num=0; + for(i=0;i<254;i++) + { + if(dyn2_master_ping(i)==DYN_NO_ERROR)// the device exists + { + ids[*num]=i; + (*num)++; + } + } +} + inline void dyn_master_enable_power(void) { GPIO_SetBits(POWER_GPIO_PORT,POWER_PIN); @@ -459,31 +668,57 @@ uint8_t dyn_master_is_power_enabled(void) } uint8_t dyn_master_ping(uint8_t id) +{ + uint8_t error; + + // generate the ping packet for the desired device + dyn_init_ping_packet(dyn_master_tx_buffer,id); + dyn_master_num_read_packets=0x01; + // enable transmission + dyn_master_enable_tx(); + // send the data + if((error=dyn_master_send())!=DYN_SUCCESS) + { + dyn_master_enable_rx(); + return error; + } + // wait for the transmission to end + if((error=dyn_master_wait_sending())!=DYN_SUCCESS) + { + dyn_master_enable_rx(); + return error; + } + dyn_master_enable_rx(); + // wait for the replay within the given timeout + error=dyn_master_receive(); + return error; +} + +uint8_t dyn2_master_ping(uint8_t id) { uint8_t error; // generate the ping packet for the desired device - dyn_init_instruction_packet(dyn_master_tx_buffer); - // set the ping instruction - dyn_set_instruction(dyn_master_tx_buffer,DYN_PING); - // set the device id - if((error=dyn_set_id(dyn_master_tx_buffer,id))==DYN_SUCCESS) - { - // set the checksum - dyn_set_checksum(dyn_master_tx_buffer); - // enable transmission - dyn_master_enable_tx(); - // send the data - dyn_master_send(); - // wait for the transmission to end - while (dyn_master_sending_packet==0x01); + dyn2_init_ping_packet(dyn_master_tx_buffer,id); + dyn_master_num_read_packets=0x01; + // enable transmission + dyn_master_enable_tx(); + // send the data + if((error=dyn2_master_send())!=DYN_SUCCESS) + { dyn_master_enable_rx(); - // wait for the replay within the given timeout - error=dyn_master_receive(); return error; } - else + // wait for the transmission to end + if((error=dyn_master_wait_sending())!=DYN_SUCCESS) + { + dyn_master_enable_rx(); return error; + } + dyn_master_enable_rx(); + // wait for the replay within the given timeout + error=dyn2_master_receive(); + return error; } uint8_t dyn_master_read_byte(uint8_t id,uint8_t address,uint8_t *data) @@ -491,6 +726,11 @@ uint8_t dyn_master_read_byte(uint8_t id,uint8_t address,uint8_t *data) return dyn_master_read(id,address,1,data); } +uint8_t dyn2_master_read_byte(uint8_t id,uint16_t address,uint8_t *data) +{ + return dyn2_master_read(id,address,1,data); +} + uint8_t dyn_master_read_word(uint8_t id,uint8_t address,uint16_t *data) { uint8_t value[2]; @@ -503,16 +743,38 @@ uint8_t dyn_master_read_word(uint8_t id,uint8_t address,uint16_t *data) return error; } +uint8_t dyn2_master_read_word(uint8_t id,uint16_t address,uint16_t *data) +{ + uint8_t value[2]; + uint8_t error; + + error=dyn2_master_read(id,address,2,value); + if(error==DYN_NO_ERROR) + (*data)=value[0]+value[1]*256; + + return error; +} + uint8_t dyn_master_read_table(uint8_t id,uint8_t address,uint8_t length,uint8_t *data) { return dyn_master_read(id,address,length,data); } +uint8_t dyn2_master_read_table(uint8_t id,uint16_t address,uint16_t length,uint8_t *data) +{ + return dyn2_master_read(id,address,length,data); +} + uint8_t dyn_master_write_byte(uint8_t id, uint8_t address, uint8_t data) { return dyn_master_write(id,address,1,&data); } +uint8_t dyn2_master_write_byte(uint8_t id, uint16_t address, uint8_t data) +{ + return dyn2_master_write(id,address,1,&data); +} + uint8_t dyn_master_write_word(uint8_t id, uint8_t address, uint16_t data) { uint8_t value[2]; @@ -522,45 +784,121 @@ uint8_t dyn_master_write_word(uint8_t id, uint8_t address, uint16_t data) return dyn_master_write(id,address,2,value); } +uint8_t dyn2_master_write_word(uint8_t id, uint16_t address, uint16_t data) +{ + uint8_t value[2]; + + value[0]=data%256; + value[1]=data/256; + return dyn2_master_write(id,address,2,value); +} + uint8_t dyn_master_write_table(uint8_t id, uint8_t address, uint8_t length, uint8_t *data) { return dyn_master_write(id,address,length,data); } -uint8_t dyn_master_reg_write(uint8_t id, uint8_t address, uint8_t length, uint8_t *data) +uint8_t dyn2_master_write_table(uint8_t id, uint16_t address, uint16_t length, uint8_t *data) { - return DYN_SUCCESS; + return dyn2_master_write(id,address,length,data); } -void dyn_master_action(void) +uint8_t dyn_master_reg_write(uint8_t id, uint8_t address, uint8_t length, uint8_t *data) { + uint8_t error; + // generate the ping packet for the desired device + dyn_init_reg_write_packet(dyn_master_tx_buffer,id,address,length,data); + dyn_master_num_read_packets=0x01; + // enable transmission + dyn_master_enable_tx(); + // send the data + if((error=dyn_master_send())!=DYN_SUCCESS) + { + dyn_master_enable_rx(); + return error; + } + // wait for the transmission to end + if((error=dyn_master_wait_sending())!=DYN_SUCCESS) + { + dyn_master_enable_rx(); + return error; + } + dyn_master_enable_rx(); + // wait for the replay within the given timeout + error=dyn_master_receive(); + return error; } -void dyn_master_sync_write(uint8_t num,uint8_t *ids,uint8_t address, uint8_t length, uint8_t *data) +uint8_t dyn2_master_reg_write(uint8_t id, uint16_t address, uint16_t length, uint8_t *data) { - uint8_t i; + uint8_t error; + // generate the ping packet for the desired device + dyn2_init_reg_write_packet(dyn_master_tx_buffer,id,address,length,data); + dyn_master_num_read_packets=0x01; + // enable transmission + dyn_master_enable_tx(); + // send the data + if((error=dyn2_master_send())!=DYN_SUCCESS) + { + dyn_master_enable_rx(); + return error; + } // wait for the transmission to end - while(dyn_master_sending_packet); + if((error=dyn_master_wait_sending())!=DYN_SUCCESS) + { + dyn_master_enable_rx(); + return error; + } + dyn_master_enable_rx(); + // wait for the replay within the given timeout + error=dyn2_master_receive(); + return error; +} + +uint8_t dyn_master_action(void) +{ + dyn_master_no_answer=0x01; + // generate the ping packet for the desired device + dyn_init_action_packet(dyn_master_tx_buffer); + // enable transmission + dyn_master_enable_tx(); + // send the data + return dyn_master_send(); +} + +uint8_t dyn2_master_action(void) +{ + dyn_master_no_answer=0x01; + // generate the ping packet for the desired device + dyn2_init_action_packet(dyn_master_tx_buffer); + // enable transmission + dyn_master_enable_tx(); + // send the data + return dyn2_master_send(); +} + +uint8_t dyn_master_sync_write(uint8_t num,uint8_t *ids,uint8_t address, uint8_t length, TWriteData *data) +{ dyn_master_no_answer=0x01; // generate the sync write packet - dyn_init_instruction_packet(dyn_master_tx_buffer); - // set the ping instruction - dyn_set_instruction(dyn_master_tx_buffer,DYN_SYNC_WRITE); - // set the start address - dyn_set_write_address(dyn_master_tx_buffer,address); - // set the data length - dyn_set_sync_write_length(dyn_master_tx_buffer,length); - // load the data for each device - for(i=0;i<num;i++) - dyn_set_sync_write_data(dyn_master_tx_buffer,ids[i],&data[i*length]); - // set the checksum - dyn_set_checksum(dyn_master_tx_buffer); + dyn_init_sync_write_packet(dyn_master_tx_buffer,num,ids,address,length,data); + // enable transmission + dyn_master_enable_tx(); + // send the data + return dyn_master_send(); +} + +uint8_t dyn2_master_sync_write(uint8_t num,uint8_t *ids,uint16_t address, uint16_t length, TWriteData *data) +{ + dyn_master_no_answer=0x01; + // generate the sync write packet + dyn2_init_sync_write_packet(dyn_master_tx_buffer,num,ids,address,length,data); // enable transmission dyn_master_enable_tx(); // send the data - dyn_master_send(); + return dyn2_master_send(); } // repeater functions @@ -568,16 +906,23 @@ uint8_t dyn_master_resend_inst_packet(uint8_t *inst_packet, uint8_t *status_pack { uint8_t error; - // generate the read packet for the desired device - dyn_init_instruction_packet(dyn_master_tx_buffer); // copy the contents of the instruction packet to the output buffer dyn_copy_packet(inst_packet,dyn_master_tx_buffer); + dyn_master_num_read_packets=0x01; // enable transmission dyn_master_enable_tx(); // send the data - dyn_master_send(); + if((error=dyn_master_send())!=DYN_SUCCESS) + { + dyn_master_enable_rx(); + return error; + } // wait for the transmission to end - while(dyn_master_sending_packet); + if((error=dyn_master_wait_sending())!=DYN_SUCCESS) + { + dyn_master_enable_rx(); + return error; + } dyn_master_enable_rx(); // wait for the replay within the given timeout error=dyn_master_receive(); @@ -590,3 +935,45 @@ uint8_t dyn_master_resend_inst_packet(uint8_t *inst_packet, uint8_t *status_pack return error; } +uint8_t dyn_master_bulk_read(uint8_t num,uint8_t *ids,uint8_t *address,uint8_t *length,TWriteData *data) +{ + uint16_t offset=0; + uint8_t i,error; + + dyn_master_num_read_packets=num; + // generate the sync write packet + dyn_init_bulk_read_packet(dyn_master_tx_buffer,num,ids,address,length); + // enable transmission + dyn_master_enable_tx(); + // send the data + if((error=dyn_master_send())!=DYN_SUCCESS) + { + dyn_master_enable_rx(); + return error; + } + // wait for the transmission to end + if((error=dyn_master_wait_sending())!=DYN_SUCCESS) + { + dyn_master_enable_rx(); + return error; + } + dyn_master_enable_rx(); + // wait for the replay within the given timeout + error=dyn_master_receive(); + if(error!=DYN_NO_ERROR) + { + dyn_master_reset(); + return error; + } + for(i=0;i<num;i++) + { + error=dyn_get_status_error(&dyn_master_rx_buffer[offset]); + if(error!=DYN_NO_ERROR) + return error; + offset+=dyn_get_read_status_data(&dyn_master_rx_buffer[offset],data[i].data_addr)+4; + } + + return DYN_SUCCESS; +} + + diff --git a/src/dynamixel_slave_uart_dma.c b/src/dynamixel_slave_uart_dma.c index 6813a6009fc1877aca0882e4286fd6ce753e3136..db8f3390ec70e38f5a488c2551fa357d3053c67a 100644 --- a/src/dynamixel_slave_uart_dma.c +++ b/src/dynamixel_slave_uart_dma.c @@ -51,7 +51,6 @@ uint8_t dyn_slave_return_level;// type of response uint8_t dyn_slave_return_delay;// delay in th response // input buffer uint8_t dyn_slave_rx_buffer[MAX_BUFFER_LEN]; -volatile uint8_t dyn_slave_receiving_header; // output buffer uint8_t dyn_slave_tx_buffer[MAX_BUFFER_LEN]; // instruction packet ready flag @@ -67,24 +66,57 @@ DMA_InitTypeDef DYN_SLAVE_DMA_RX_InitStructure; // interrupt handlers void DYN_SLAVE_IRQHandler(void) { - if(USART_GetITStatus(DYN_SLAVE, USART_IT_TC) != RESET) + static uint8_t num_bytes=0; + uint8_t data; + + if(USART_GetITStatus(DYN_SLAVE, USART_IT_RXNE) != RESET) + { + USART_ClearFlag(DYN_SLAVE,USART_FLAG_RXNE); + data=USART_ReceiveData(DYN_SLAVE); + switch(num_bytes) + { + case 0: if(data==0xFF) + { + dyn_slave_rx_buffer[num_bytes]=data; + num_bytes++; + } + break; + case 1: if(data==0xFF) + { + dyn_slave_rx_buffer[num_bytes]=data; + num_bytes++; + } + else num_bytes--; + break; + case 2: if(data!=0xFF) + { + dyn_slave_rx_buffer[num_bytes]=data; + num_bytes++; + } + break; + case 3: dyn_slave_rx_buffer[num_bytes]=data; + num_bytes=0; + /* disable USART RX interrupts */ + USART_ITConfig(DYN_SLAVE,USART_IT_RXNE,DISABLE); + /* enable DMA RX */ + DMA_SetCurrDataCounter(DYN_SLAVE_RX_DMA_STREAM, data); + DMA_Cmd(DYN_SLAVE_RX_DMA_STREAM,ENABLE); + USART_DMACmd(DYN_SLAVE, USART_DMAReq_Rx, ENABLE); + break; + default: break; + } + } + else if(USART_GetITStatus(DYN_SLAVE, USART_IT_TC) != RESET) { USART_ClearFlag(DYN_SLAVE,USART_FLAG_TC); USART_ITConfig(DYN_SLAVE, USART_IT_TC, DISABLE); dyn_slave_sending_packet=0x00; - // set up the DMA RX transaction - DYN_SLAVE_DMA_RX_InitStructure.DMA_BufferSize = 4; - DYN_SLAVE_DMA_RX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)dyn_slave_rx_buffer; - DMA_Init(DYN_SLAVE_RX_DMA_STREAM,&DYN_SLAVE_DMA_RX_InitStructure); - DMA_ITConfig(DYN_SLAVE_RX_DMA_STREAM,DMA_IT_TC,ENABLE); - DMA_Cmd(DYN_SLAVE_RX_DMA_STREAM,ENABLE); - USART_DMACmd(DYN_SLAVE, USART_DMAReq_Rx, ENABLE); - dyn_slave_receiving_header=0x01; } } void DYN_SLAVE_DMA_TX_IRQHandler(void) { + DMA_Cmd(DYN_SLAVE_TX_DMA_STREAM,DISABLE); DMA_ClearFlag(DYN_SLAVE_TX_DMA_STREAM,DYN_SLAVE_TX_DMA_FLAG_TCIF); DMA_ClearITPendingBit(DYN_SLAVE_TX_DMA_STREAM,DYN_SLAVE_TX_DMA_FLAG_TCIF); USART_ITConfig(DYN_SLAVE, USART_IT_TC, ENABLE); @@ -92,24 +124,13 @@ void DYN_SLAVE_DMA_TX_IRQHandler(void) void DYN_SLAVE_DMA_RX_IRQHandler(void) { - if(dyn_slave_receiving_header==0x01) - { - DMA_ClearFlag(DYN_SLAVE_RX_DMA_STREAM,DYN_SLAVE_RX_DMA_FLAG_TCIF); - DMA_ClearITPendingBit(DYN_SLAVE_RX_DMA_STREAM,DYN_SLAVE_RX_DMA_FLAG_TCIF); - DYN_SLAVE_DMA_RX_InitStructure.DMA_BufferSize = dyn_get_length(dyn_slave_rx_buffer); - DYN_SLAVE_DMA_RX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&dyn_slave_rx_buffer[4]; - DMA_Init(DYN_SLAVE_RX_DMA_STREAM,&DYN_SLAVE_DMA_RX_InitStructure); - DMA_Cmd(DYN_SLAVE_RX_DMA_STREAM,ENABLE); - USART_DMACmd(DYN_SLAVE, USART_DMAReq_Rx, ENABLE); - dyn_slave_receiving_header=0x00; - } - else - { - DMA_ClearFlag(DYN_SLAVE_RX_DMA_STREAM,DYN_SLAVE_RX_DMA_FLAG_TCIF); - DMA_ClearITPendingBit(DYN_SLAVE_RX_DMA_STREAM,DYN_SLAVE_RX_DMA_FLAG_TCIF); - DMA_ITConfig(DYN_SLAVE_RX_DMA_STREAM,DMA_IT_TC,DISABLE); - dyn_slave_packet_ready=0x01; - } + DMA_Cmd(DYN_SLAVE_RX_DMA_STREAM,DISABLE); + DMA_ClearFlag(DYN_SLAVE_RX_DMA_STREAM,DYN_SLAVE_RX_DMA_FLAG_TCIF); + DMA_ClearITPendingBit(DYN_SLAVE_RX_DMA_STREAM,DYN_SLAVE_RX_DMA_FLAG_TCIF); + USART_DMACmd(DYN_SLAVE, USART_DMAReq_Rx, DISABLE); + // enable USART RX interrupt + USART_ITConfig(DYN_SLAVE,USART_IT_RXNE,ENABLE); + dyn_slave_packet_ready=0x01; } // public functions @@ -149,7 +170,6 @@ void dyn_slave_init(void) // initialize the flags dyn_slave_packet_ready=0x00; dyn_slave_sending_packet=0x00; - dyn_slave_receiving_header=0x01; USART_DeInit(DYN_SLAVE); USART_StructInit(&USART_InitStructure); @@ -163,14 +183,39 @@ void dyn_slave_init(void) USART_Init(DYN_SLAVE, &USART_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = DYN_SLAVE_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); - USART_ITConfig(DYN_SLAVE, USART_IT_RXNE | USART_IT_ORE | USART_IT_TXE | USART_IT_CTS | USART_IT_LBD | USART_IT_IDLE | USART_IT_PE | USART_IT_ERR | USART_IT_TC, DISABLE); - USART_ClearFlag(DYN_SLAVE,USART_FLAG_RXNE | USART_FLAG_ORE | USART_FLAG_TXE | USART_FLAG_CTS | USART_FLAG_LBD | USART_FLAG_IDLE | USART_FLAG_PE | USART_FLAG_TC); - USART_ClearITPendingBit(DYN_SLAVE, USART_FLAG_RXNE | USART_FLAG_ORE | USART_FLAG_TXE | USART_FLAG_CTS | USART_FLAG_LBD | USART_FLAG_IDLE | USART_FLAG_PE | USART_FLAG_TC); + /* disable all interrupts of the USART */ + USART_ITConfig(DYN_SLAVE, USART_IT_RXNE | + USART_IT_ORE | + USART_IT_TXE | + USART_IT_CTS | + USART_IT_LBD | + USART_IT_IDLE | + USART_IT_PE | + USART_IT_ERR | + USART_IT_TC, DISABLE); + /* Clear all USART interrupt flags */ + USART_ClearFlag(DYN_SLAVE,USART_FLAG_RXNE | + USART_FLAG_ORE | + USART_FLAG_TXE | + USART_FLAG_CTS | + USART_FLAG_LBD | + USART_FLAG_IDLE | + USART_FLAG_PE | + USART_FLAG_TC); + /* Clear all USART interrupt pending bits */ + USART_ClearITPendingBit(DYN_SLAVE, USART_FLAG_RXNE | + USART_FLAG_ORE | + USART_FLAG_TXE | + USART_FLAG_CTS | + USART_FLAG_LBD | + USART_FLAG_IDLE | + USART_FLAG_PE | + USART_FLAG_TC); /* Enable the DYN_SLAVE3 */ USART_Cmd(DYN_SLAVE, ENABLE); @@ -204,7 +249,6 @@ void dyn_slave_init(void) /* Configure RX DMA */ DMA_DeInit(DYN_SLAVE_RX_DMA_STREAM); - DYN_SLAVE_DMA_RX_InitStructure.DMA_BufferSize = 4;// transfer the first 3 bytes DYN_SLAVE_DMA_RX_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DYN_SLAVE_DMA_RX_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; DYN_SLAVE_DMA_RX_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; @@ -218,7 +262,7 @@ void dyn_slave_init(void) DYN_SLAVE_DMA_RX_InitStructure.DMA_Priority = DMA_Priority_High; DYN_SLAVE_DMA_RX_InitStructure.DMA_Channel = DYN_SLAVE_RX_DMA_CHANNEL; DYN_SLAVE_DMA_RX_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; - DYN_SLAVE_DMA_RX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)dyn_slave_rx_buffer; + DYN_SLAVE_DMA_RX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&dyn_slave_rx_buffer[4]; DMA_Init(DYN_SLAVE_RX_DMA_STREAM,&DYN_SLAVE_DMA_RX_InitStructure); /* initialize DMA interrupts */ NVIC_InitStructure.NVIC_IRQChannel = DYN_SLAVE_DMA_RX_IRQn; @@ -229,8 +273,8 @@ void dyn_slave_init(void) DMA_ITConfig(DYN_SLAVE_RX_DMA_STREAM,DMA_IT_TC,ENABLE); DMA_ITConfig(DYN_SLAVE_RX_DMA_STREAM,DMA_IT_HT | DMA_IT_TE | DMA_IT_FE | DMA_IT_DME,DISABLE); - DMA_Cmd(DYN_SLAVE_RX_DMA_STREAM,ENABLE); - USART_DMACmd(DYN_SLAVE, USART_DMAReq_Rx, ENABLE); + /* enable USART RX interrupts */ + USART_ITConfig(DYN_SLAVE,USART_IT_RXNE,ENABLE); } inline void dyn_slave_set_address(uint8_t id) @@ -277,11 +321,7 @@ void dyn_slave_send_status_packet(uint8_t error,uint8_t length, uint8_t *data) // wait until the previous transmission has ended (if any) while(dyn_slave_sending_packet==0x01); // create the status packet - dyn_init_status_packet(dyn_slave_tx_buffer); - dyn_set_status_error(dyn_slave_tx_buffer,error); - dyn_set_id(dyn_slave_tx_buffer,dyn_slave_address); - dyn_set_status_data(dyn_slave_tx_buffer,length,data); - dyn_set_checksum(dyn_slave_tx_buffer); + dyn_init_status_packet(dyn_slave_tx_buffer,dyn_slave_address,error,length,data); // set the DMA transfer DMA_SetCurrDataCounter(DYN_SLAVE_TX_DMA_STREAM,dyn_get_length(dyn_slave_tx_buffer)+4); DMA_Cmd(DYN_SLAVE_TX_DMA_STREAM,ENABLE); @@ -295,7 +335,6 @@ void dyn_slave_resend_status_packet(uint8_t *packet) // wait until the previous transmission has ended (if any) while(dyn_slave_sending_packet==0x01); // create the status packet - dyn_init_status_packet(dyn_slave_tx_buffer); dyn_copy_packet(packet,dyn_slave_tx_buffer); // set the DMA transfer DMA_SetCurrDataCounter(DYN_SLAVE_TX_DMA_STREAM,dyn_get_length(dyn_slave_tx_buffer)+4); @@ -305,15 +344,3 @@ void dyn_slave_resend_status_packet(uint8_t *packet) dyn_slave_sending_packet=0x01; } -void dyn_slave_reset(void) -{ - dyn_slave_sending_packet=0x00; - // set up the DMA RX transaction - DYN_SLAVE_DMA_RX_InitStructure.DMA_BufferSize = 4; - DYN_SLAVE_DMA_RX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)dyn_slave_rx_buffer; - DMA_Init(DYN_SLAVE_RX_DMA_STREAM,&DYN_SLAVE_DMA_RX_InitStructure); - DMA_ITConfig(DYN_SLAVE_RX_DMA_STREAM,DMA_IT_TC,ENABLE); - DMA_Cmd(DYN_SLAVE_RX_DMA_STREAM,ENABLE); - USART_DMACmd(DYN_SLAVE, USART_DMAReq_Rx, ENABLE); - dyn_slave_receiving_header=0x01; -} diff --git a/src/motion_manager.c b/src/motion_manager.c index 5d260ac2af1da4fb47eea4304ba15e2a58758ee9..0650f7bc74c50fbc4f2cc1fc940423a5387759f0 100644 --- a/src/motion_manager.c +++ b/src/motion_manager.c @@ -100,14 +100,14 @@ void manager_balance(void) int16_t x_error=0.0; int16_t y_error=0.0; - manager_servos[10].current_value+=(y_error*ram_data[BIOLOID_MM_PELVIS_ROLL_L]*11)/2500; - manager_servos[9].current_value+=(y_error*ram_data[BIOLOID_MM_PELVIS_ROLL_R]*11)/2500; - manager_servos[18].current_value-=(y_error*ram_data[BIOLOID_MM_ANKLE_ROLL_L]*11)/2500; - manager_servos[17].current_value-=(y_error*ram_data[BIOLOID_MM_ANKLE_ROLL_R]*11)/2500; - manager_servos[16].current_value-=(x_error*ram_data[BIOLOID_MM_ANKLE_PITCH_L]*11)/2500; - manager_servos[15].current_value+=(x_error*ram_data[BIOLOID_MM_ANKLE_PITCH_R]*11)/2500; - manager_servos[14].current_value-=(x_error*ram_data[BIOLOID_MM_KNEE_L]*11)/2500; - manager_servos[13].current_value+=(x_error*ram_data[BIOLOID_MM_KNEE_R]*11)/2500; + manager_servos[10].current_value+=(y_error*ram_data[BIOLOID_MM_PELVIS_ROLL_GAIN_L]*11)/2500; + manager_servos[9].current_value+=(y_error*ram_data[BIOLOID_MM_PELVIS_ROLL_GAIN_R]*11)/2500; + manager_servos[18].current_value-=(y_error*ram_data[BIOLOID_MM_ANKLE_ROLL_GAIN_L]*11)/2500; + manager_servos[17].current_value-=(y_error*ram_data[BIOLOID_MM_ANKLE_ROLL_GAIN_R]*11)/2500; + manager_servos[16].current_value-=(x_error*ram_data[BIOLOID_MM_ANKLE_PITCH_GAIN_L]*11)/2500; + manager_servos[15].current_value+=(x_error*ram_data[BIOLOID_MM_ANKLE_PITCH_GAIN_R]*11)/2500; + manager_servos[14].current_value-=(x_error*ram_data[BIOLOID_MM_KNEE_GAIN_L]*11)/2500; + manager_servos[13].current_value+=(x_error*ram_data[BIOLOID_MM_KNEE_GAIN_R]*11)/2500; } // interrupt handlers @@ -266,7 +266,7 @@ void manager_init(uint16_t period_us) /* motion timer configuration */ TIM_TimeBaseStructure.TIM_Period = 0xFFFF; - TIM_TimeBaseStructure.TIM_Prescaler = 82; + TIM_TimeBaseStructure.TIM_Prescaler = 72; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(MOTION_TIMER,&TIM_TimeBaseStructure); diff --git a/src/time.c b/src/time.c index e36a0d2faf74a0998930771b2746028a49c1e8df..44dd1b79c4c7c99b968312e1dfbc1bcbe9ab6bc6 100644 --- a/src/time.c +++ b/src/time.c @@ -1,6 +1,7 @@ #include "time.h" static __IO uint32_t timing_delay; +uint32_t clocks_per_us; /******************************************************************************* * Function Name : SysTickHandler @@ -18,9 +19,23 @@ void SysTick_Handler(void) // public functions void time_init(void) { + TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; + // set the time base to 1ms SysTick_Config(SystemCoreClock / 1000); NVIC_SetPriority(SysTick_IRQn,0); + + RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); + + TIM_TimeBaseStructure.TIM_Period = 0xFFFF; + TIM_TimeBaseStructure.TIM_Prescaler = 0; + TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; + TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseStructure.TIM_RepetitionCounter=0x0000; + TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure); + TIM_SetCounter(TIM1,0); + + clocks_per_us=(SystemCoreClock/1000000)+1; } void delay_ms(__IO uint32_t time) @@ -30,4 +45,16 @@ void delay_ms(__IO uint32_t time) while(timing_delay!=0); } +void delay_us(uint32_t us) // microseconds +{ + uint32_t clocks,current; + + clocks=clocks_per_us*us; + TIM_SetCounter(TIM1,0); + TIM_Cmd(TIM1, ENABLE); + do{ + current=TIM_GetCounter(TIM1); + }while(current<clocks); + TIM_Cmd(TIM1, DISABLE); +}