Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RP2040 assertion "hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX" failed: #628

Closed
ndinsmore opened this issue Feb 3, 2021 · 3 comments

Comments

@ndinsmore
Copy link
Contributor

Set up
[Mandatory] Provide details of your setup help us to reproduce the issue as quick as possible

  • PC OS : macOS 10.15
  • Board : pi pico
  • Firmware: examples/device/usb/UAC2_headset modified to write square wave to mic see below
  • Using the tinyUSB master repo not the RPI repo
void fill_mic_buffer(int16_t num){
   static uint8_t wave_counter = 0;
   static int16_t wave_state = 20000;
   int16_t *dst = mic_buf;
   int16_t *limit = mic_buf + num;
   
   //THis code should make a 1000 hz squarewave
   while (dst < limit) {
           wave_counter = (wave_counter == 48) ? 0 : (wave_counter+1);
           wave_state = (wave_counter == 0 ) ? (-wave_state) : wave_state;
           *dst++ = (int16_t) wave_state;
   }
}
bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t *buffer, uint16_t buf_size) {
   return true;
}

bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) {
   (void) rhport;     (void) itf;    (void) ep_in;    (void) cur_alt_setting;
   
   const uint16_t num_to_buf = 128;
   fill_mic_buffer(num_to_buf);
   tud_audio_write((uint8_t *) mic_buf, num_to_buf * 2 /*/ 2*/); 
   return true;
}

//--------------------------------------------------------------------+
// AUDIO Task
//--------------------------------------------------------------------+

void audio_task(void) {

   if (spk_data_size) {
       spk_data_size = 0;
   }
}

Describe the bug
Code will run then mysteriously stop, debugging and turning on the pico_info instrumentation points to the _hw_endpoint_alloc function line 84:

static void _hw_endpoint_alloc(struct hw_endpoint *ep)
{
uint size = TU_MIN(64, ep->wMaxPacketSize);
// Assumes single buffered for now
ep->hw_data_buf = next_buffer_ptr;
next_buffer_ptr += size;
// Bits 0-5 are ignored by the controller so make sure these are 0
if ((uintptr_t)next_buffer_ptr & 0b111111u)
{
// Round up to the next 64
uint32_t fixptr = (uintptr_t)next_buffer_ptr;
fixptr &= ~0b111111u;
fixptr += 64;
pico_info("Rounding non 64 byte boundary buffer up from %x to %x\n", (uintptr_t)next_buffer_ptr, fixptr);
next_buffer_ptr = (uint8_t*)fixptr;
}
assert(((uintptr_t)next_buffer_ptr & 0b111111u) == 0);
uint dpram_offset = hw_data_offset(ep->hw_data_buf);
assert(hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX);
pico_info("Alloced %d bytes at offset 0x%x (0x%p) for ep %d %s\n",
size,
dpram_offset,
ep->hw_data_buf,
ep->num,
ep_dir_string[ep->in]);
// Fill in endpoint control register with buffer offset
uint32_t reg = EP_CTRL_ENABLE_BITS
| EP_CTRL_INTERRUPT_PER_BUFFER
| (ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB)
| dpram_offset;
*ep->endpoint_control = reg;
}

In that function it isn't clear to me where the memory reuse happens it looks like it just keeps pushing the buffer to the next set of memory.

if if add the following code the the device seems to run properly, though I have to admit I don't understand the system well enough to know if it is allowed. All it is doing is pointing next_buffer_ptr to where it is initially initialized.

 if(hw_data_offset(next_buffer_ptr) <= (USB_DPRAM_MAX+size)){
        next_buffer_ptr = &usb_dpram->epx_data[0];
    }

I that I am fairly certain that the assert(hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX); is wrong and should be assert(hw_data_offset(next_buffer_ptr) <= (USB_DPRAM_MAX+size)); to account for the size of the buffer and prevent a buffer overflow.

To reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. See error

Screenshots
If applicable, add screenshots, bus capture to help explain your problem.

Log
This is not the whole long just the portion before is fails.

hw_endpoint_xfer ep 1 in total_len 98, start=1
Start transfer of total len 98 on ep 1 in
buffer buf_status 0x00000004
tx 64 bytes (buf_ctrl 0x00000040)
Last buf (34 bytes left)
buffer control (0x50100088) <- 0xe422
buf_status 0x00000004
tx 34 bytes (buf_ctrl 0x00006022)
Completed transfer of 98 bytes on ep 1 in
control (0x50100088) <- 0x8440
hw_endpoint_xfer ep 1 out total_len 192, start=1
Start transfer of total len 192 on ep 1 out
buffbuf_status 0x00000008
rx 64 bytes (buf_ctrl 0x0000a040)
buffer control (0x5010008C) <- 0x440
buf_status 0x00000008
rx 64 bytes (buf_ctrl 0x00008040)
Last buf (64 bytes left)
buffer control (0x5010008C) <- 0x6440
buf_status 0x00000008
rx 64 bytes (buf_ctrl 0x0000e040)
Completed transfer of 192 bytes on ep 1 out
er control (0x5010008C) <- 0x2440
hw_endpoint_xfer ep 1 in total_len 98, start=1
Start transfer of total len 98 on ep 1 in
buf_status 0x00000004
tx 64 bytes (buf_ctrl 0x00000040)
Last buf (34 bytes left)
buffer control (0x50100088) <- 0xe422
buf_status 0x00000004
tx 34 bytes (buf_ctrl 0x00006022)
Completed transfer of 98 bytes on ep 1 in
buffer control (0x50100088) <- 0x8440
hw_endpoint_xfer ep 1 out total_len 192, start=1
Start transfer of total len 192 on ep 1 out
buffer control (0x5010008C) <- 0x440
dcd_edpt_close 0 01
hw_endpoint_xfer ep 0 in total_len 0, start=1
Start transfer of total len 0 on ep 0 in
Last buf (0 bytes left)
buf_status 0x00000001
tx 0 bytes (buf_ctrl 0x00006000)
Completed transfer of 0 bytes on ep 0 in
buffer control (0x50100080) <- 0xe400
hw_endpoint_xfer ep 1 in total_len 98, start=1
Start transfer of total len 98 on ep 1 in
buffer control (0x50100088) <- 0x8440
dcd_edpt0_status_complete 0
dcd_edpt_close 0 81
hw_endpoint_xfer ep 0 in total_len 0, start=1
Start transfer of total len 0 on ep 0 in
Last buf (0 bytes left)
buf_status 0x00000001
tx 0 bytes (buf_ctrl 0x00006000)
Completed transfer of 0 bytes on ep 0 in
buffer control (0x50100080) <- 0xe400
dcd_edpt0_status_complete 0
assertion "hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX" failed: file "...../tinyusb/src/portable/raspberrypi/rp2040/dcd_rp2040.c", line 84, function: _hw_endpoint_alloc
@liamfraser
Copy link
Collaborator

This should be fixed by PR #642

@howard0su
Copy link
Contributor

I still see the same issue with latest master. I think the issue is back again.

@howard0su
Copy link
Contributor

I proposed a PR #1802 to fix this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants