STM32G431 circular DMA with TIM17 + DMAMUX - timer

I've been trying for a couple of days now, to create a simple DMA program for the G4. But without HAL (using libopencm3). The goal is to configure DMA to read data (in circular mode) from buffer and send them to TIM17_CCR1. I've made the code work in HAL previously, but have no luck with libopencm3. I've managed to transfer data from buffer to the OCR in mem2mem mode (even though i need mem2perif) just to try. But I have no idea on how to start with mem2perif. Configuring DMA is no big deal, but I'm lost in the DMAMUX part.
Do you even have to configure it? How do you configure it the right way? I'm totally lost in ST's documentation and can't find any existing code using DMAMUX without HAL.
Do any of you have any examples I could look at? Best would be some bare metal C so I could check out the registers. Anything that would help some documents (else than STs own)? It would be much appreciated.
Thanks a lot!

I've got it working even with the library, just needed one more day of testing :(
Here is the code for anybody interesrted:
gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_FRONT_LED | GPIO_BACK_LED);
gpio_set_output_options(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_FRONT_LED | GPIO_BACK_LED);
gpio_set_af(GPIOB, GPIO_AF10, GPIO_BACK_LED);
//Setup for back led
dma_set_priority(DMA1, DMA_CHANNEL1, DMA_CCR_PL_LOW);
dma_set_memory_size(DMA1, DMA_CHANNEL1, DMA_CCR_MSIZE_8BIT);
dma_set_peripheral_size(DMA1, DMA_CHANNEL1, DMA_CCR_PSIZE_16BIT);
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL1);
dma_enable_circular_mode(DMA1, DMA_CHANNEL1);
dma_set_read_from_memory(DMA1, DMA_CHANNEL1);
dmamux_set_dma_channel_request(DMAMUX1, DMA_CHANNEL1, DMAMUX_CxCR_DMAREQ_ID_TIM17_CH1);
dma_set_peripheral_address(DMA1, DMA_CHANNEL1, (uint32_t)&TIM17_CCR1);
dma_set_memory_address(DMA1, DMA_CHANNEL1, (uint32_t)&ledBackBuffer);
dma_set_number_of_data(DMA1, DMA_CHANNEL1, LED_BACK_BUFFER_SIZE);
timer_enable_preload(TIM17);
timer_update_on_overflow(TIM17);
timer_set_dma_on_update_event(TIM17);
timer_enable_irq(TIM17, TIM_DIER_CC1DE);
timer_generate_event(TIM17, TIM_EGR_CC1G);
timer_set_oc_mode(TIM17, TIM_OC1, TIM_OCM_PWM1);
timer_enable_oc_output(TIM17, TIM_OC1);
timer_enable_break_main_output(TIM17);
timer_set_period(TIM17, 179);
timer_enable_counter(TIM17);
dma_enable_channel(DMA1, DMA_CHANNEL1);
ledBackBuffer is basic uint8_t array filled with data to be transmitted to all the LEDs.

Related

AT91SAM9G45C Software-Reset

I am using a board with AT91SAM9G45C processor, booting from an SD-card. That works. Now i extended the software with a filetransfer function, to upload a new application software to the SD-card. This part also works.
My problem is, if i create a reset on the controller (watchdog or ResetController)
AT91C_BASE_RSTC->RSTC_RCR = AT91C_RSTC_KEY | AT91C_RSTC_PERRST | AT91C_RSTC_PROCRST;
while(AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_SRCMP);
//Jump to the reset vector
(*(void(*)())0)();
, the controller starts only the programm in RAM (initialisation, ...) but dont load the new programm from SD-card. Only after a reset with power-supply off, the controller reloads the programm from SD-card.
My question: how can a software-reset created that reloads the programm new from the SD-card?
can someone help me?
Fritz

BlueNRG Bluetooth: read central device name

I'm using the STM BlueNRG-MS chip on my peripheral device and after connection I'd like to read the name of the connected central device (android phone).
I thought I can do this directly in my user_notify routine which is registered as hci callback
/* Initialize the Host-Controller Interface */
hci_init(user_notify, NULL);
So on the EVT_LE_CONN_COMPLETE event, I take the provided handle for the central device and I use aci_gatt_read_using_charac_uuid() to read what I thought is the characteristic with the device name (uuid 0x2a00).
case EVT_LE_META_EVENT:
{
evt_le_meta_event *evt = (void *)event_pckt->data;
switch(evt->subevent){
case EVT_LE_CONN_COMPLETE:
{
evt_le_connection_complete *cc = (void *)evt->data;
GAP_ConnectionComplete_CB(cc->peer_bdaddr, cc->handle);
uint16_t uuid = 0x2a00;
resp = aci_gatt_read_using_charac_uuid(cc->handle, 0, 1, UUID_TYPE_16, (uint8_t*)&uuid);
LOG("GATT read status: %d", resp);
enqueEvent(EVENT_BLE_CONNECTED);
}
break;
}
}
Long story short, it doesn't work. First thing I'm not sure about is, what is the start_handle and end_handle parameter of aci_gatt_read_using_charac_uuid(), it returns ERR_INVALID_HCI_CMD_PARAMS.
Can someone shed some light here?
update
What also puzzles me is that the function aci_gatt_read_using_charac_uuid() is nowehere referenced in the BlueNRG-MS Programming Guidelines.
update2
I changed the function call to aci_gatt_read_using_charac_uuid(cc->handle, 0x0001, 0xffff, UUID_TYPE_16, (uint8_t*)&uuid); but I still get the ERR_INVALID_HCI_CMD_PARAMS. What which paramter could even be invalid? The uuid exists, I can read the device name if I use the BlueNRG GUI with a bluetooth dongle.
update3
Has anyone ever used this function or somehow managed to read a characteristic from a central device? I'd highly appreciate any help or hint.
Here you go, The BlueNRG-MS Bluetooth® LE stack application command interface (ACI) - User manual
page 75 - 4.6.25 Aci_Gatt_Read_Charac_Using_UUID()
and make sure you have called Aci_Gatt_Init()
The user manual is last revised July 2019, the document you link to is from 2018, don't know if this is why ?
The start_handle and end_handle is the range of handles in your service as pictured here -
Here is a discussion to the closest thing I could find to match your question.
As it turned out there are two bugs in the BlueNRG API.
In bluenrg_aci_const.h file the OCF code OCF_GATT_READ_USING_CHARAC_UUID shall be 0x119 instead of 0x109.
And in the implementation of the aci_gatt_read_using_charac_uuid() function, there is a missing setting on event:
rq.event = EVT_CMD_STATUS;
Patching them fixed the issue.

CANOPEN SYNC timeout after enable Operation

I am a newbie in CANOPEN. I wrote a program that read actual position via PDO1 (default is statusword + actual position).
void canopen_init() {
// code1 setup PDO mapping
nmtPreOperation();
disablePDO(PDO_TX1_CONFIG_COMM);
setTransmissionTypePDO(PDO_TX1_CONFIG_COMM, 1);
setInhibitTimePDO(PDO_TX1_CONFIG_COMM, 0);
setEventTimePDO(PDO_TX1_CONFIG_COMM, 0);
enablePDO(PDO_TX1_CONFIG_COMM);
setCyclePeriod(1000);
setSyncWindow(100);
//code 2: enable OPeration
readyToSwitchOn();
switchOn();
enableOperation();
motionStart();
// code 3
nmtActiveNode();
}
int main (void) {
canopen_init();
while {
delay_ms(1);
send_sync();
}
}
If I remove "code 2" (the servo is in Switch_on_disable status), i can read position each time sync send. But if i use "code 2", the driver has error "sync frame timeout". I dont know driver has problem or my code has problem. Does my code has problem? thank you!
I don't know what protocol stack this is or how it works, but these:
setCyclePeriod(1000);
setSyncWindow(100);
likely correspond to these OD entries :
Object 1006h: Communication cycle period (CiA 301 7.5.2.6)
Object 1007h: Synchronous window length (CiA 301 7.5.2.7)
They set the SYNC interval and time window for synchronous PDOs respectively. The latter is described by the standard as:
If the synchronous window length expires all synchronous TPDOs may be discarded and an EMCY message may be transmitted; all synchronous RPDOs may be discarded until the next SYNC message is received. Synchronous RPDO processing is resumed with the next SYNC message.
Now if you set this sync time window to 100us but have a sloppy busy-wait delay delay_ms(1), then that doesn't add up. If you write zero to Object 1007h, you disable the sync window feature. I suppose setSyncWindow(0); might do that. You can try to do that to see if that's the issue. If so, you have to drop your busy-wait in favour for proper hardware timers, one for the SYNC period and one for PDO timeout (if you must use that feature).
Problem fixed. Due to much EMI from servo, that make my controller didn't work properly. After isolating, it worked very well :)!

Implementation of time in Zynq

I'm trying to do a simple STANDALONE application for Zynq. I want to use the 'time.h' to manipulate date/time. I know that there is no hardware implementation on a stanalone BSP, but I want to wire it up on my own.
During compilation, when I call 'time(NULL)' I get a error, that there is no implementation of '_gettimeofday()'. I've found it in and implemented it according to the function definition, so that the errors disappear and everything looks ok, but when I run my project on hardware, I see only zeroes from time().
Can anybody help?
Regards,
G2
Ok, I've done some research, and found this link. This is almost what I'v been searching, but instead of '_times()' I needed '_gettimeofday()' and this is my implementation:
int _gettimeofday(struct timeval *__p, void *__tz)
{
__p->tv_sec = (systemUsCounter / 1000000);
__p->tv_usec = systemUsCounter;
return 0;
}
I left the '__tz' pointer with no chainges.
So this is basicly how to utilize 'time.h' in a standalone application on Zynq.

iOS 6 - Bluetooth LE disconnect

Ok what the heck is up with iOS6 and how it handles Bluetooth LE disconnections? Before the device would disconnect immediately but now, for some strange reason, the device waits to disconnect for about 30-60 seconds. I need it to disconnect ASAFP!
I've been searing all over the internet trying to figure out how to initiate an immediate disconnection from the peripheral and I found this nifty email that explains a workaround is to unsubscribe from notifications on the service characteristics.
Now I think I'm doing that.. When I want to disconnect I call [connected_device setNotifyValue:NO forCharacteristic:connected_characteristic]
Then, in the didUpdateNotificationStateForCharacteristic function, I have...
if((int)characteristic.isNotifying == 0){
[manager cancelPeripheralConnection:peripheral];
}
In the function didDisconnectPeripheral...
connected_peripheral = nil;
connected_characteristic = nil;
[connected_peripheral release];
[connected_characteristic release];
I've also taken a good hard look at Apple's CoreBluetooth Temperature Sensor example but it hasn't really helped much....
Any help on this would be amazing!! I just don't know what I'm missing.....
UPDATE: It looks like the app needs to be connected to the bluetooth device for at least a minute before it is allowed to disconnect. If the app is connected for over a minute it will disconnect immediately when the command is sent. Otherwise, it will wait until that one minute mark to actually disconnect.
UPDATE: When I try to disconnect before the one minute mark, I get the following output to the log when the device actually disconnects.
Oct 24 16:49:35 Christophers-iPhone awdd[8168] <Error>: libMobileGestalt copySystemVersionDictionaryValue: Could not lookup ReleaseType from system version dictionary
Oct 24 16:49:35 Christophers-iPhone awdd[8168] <Error>: CoreLocation: CLClient is deprecated. Will be obsolete soon.
According to Apple, this new feature is "by design".
The way we resolved this issue was to send a command to the Peripheral and have it disconnect from its end. If you do this, then the disconnect is immediate. I do not know why Apple changed this behavior from iOS5 to iOS6 but they must have had their reasons. Of course this solution only works if you have access to the Peripheral firmware and can change it. If there is a different solution, then we have not found it.
That was a bug in iOS 6.0, in 6.1 it's fixed.

Resources