{"record":{"id":"79e072eb350b575e","repo":"embassy-rs/embassy","slug":"endpoint-memory-full","errorCode":null,"errorMessage":"Endpoint memory full","messagePattern":"Endpoint memory full","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-stm32/src/usb/usb.rs","lineNumber":361,"sourceCode":"        // Initialize the bus so that it signals that power is available\n        BUS_WAKER.wake();\n\n        Self {\n            phantom: PhantomData,\n            alloc: [EndpointData {\n                ep_type: EndpointType::Bulk,\n                used_in: false,\n                used_out: false,\n            }; EP_COUNT],\n            ep_mem_free: EP_COUNT as u16 * 8, // for each EP, 4 regs, so 8 bytes\n        }\n    }\n\n    fn alloc_ep_mem(&mut self, len: u16) -> u16 {\n        assert!(len as usize % USBRAM_ALIGN == 0);\n        let addr = self.ep_mem_free;\n        if addr + len > USBRAM_SIZE as _ {\n            panic!(\"Endpoint memory full\");\n        }\n        self.ep_mem_free += len;\n        addr\n    }\n\n    fn is_endpoint_available<D: Dir>(&self, index: usize, ep_type: EndpointType) -> bool {\n        if index == 0 && ep_type != EndpointType::Control {\n            return false; // EP0 is reserved for control\n        }\n\n        let ep = match self.alloc.get(index) {\n            Some(ep) => ep,\n            None => return false,\n        };\n\n        let used = ep.used_out || ep.used_in;\n\n        if used && ep.ep_type == EndpointType::Isochronous {","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-stm32/src/usb/usb.rs#L343-L379","documentation":"STM32 USB devices have a small shared packet-buffer RAM (USBRAM, typically 512–4096 bytes). alloc_ep_mem is a bump allocator over that region; when an endpoint allocation would push past USBRAM_SIZE, the driver panics because the hardware physically cannot back more buffers.","triggerScenarios":"alloc_endpoint calls whose cumulative buffer sizes exceed USBRAM_SIZE — e.g. many endpoints with large max_packet_size, or several bidirectional ISO/Bulk endpoints on a 512–1024-byte USBRAM part.","commonSituations":"Adding a second interface (e.g. CDC-ACM + MSC + custom vendor) and exhausting 512 B of USBRAM; bumping packet sizes to 512 for speed on a part with 1 KB USBRAM; iterating during development, growing buffers until total allocation overflows.","solutions":["Reduce endpoint max_packet_size values (e.g. 512 -> 64 for bulk FS)","Drop or combine endpoints/interfaces, or use fewer bidirectional endpoints","Move to a chip variant with larger USBRAM (check USBRAM_SIZE for your part; 32-bit usbram parts usually have 1–4 KB)","Compute your budget: sum of (IN+OUT buffer sizes + 2-byte Tx/Rx counts, aligned) and keep it under USBRAM_SIZE before adding endpoints"],"exampleFix":"// before\nlet ep_in = dev.alloc_endpoint(EndpointType::Bulk, 512, 512)?;\nlet ep_out = dev.alloc_endpoint(EndpointType::Bulk, 512, 512)?; // + more eps -> \"Endpoint memory full\"\n// after\nlet ep_in = dev.alloc_endpoint(EndpointType::Bulk, 64, 64)?;\nlet ep_out = dev.alloc_endpoint(EndpointType::Bulk, 64, 64)?;","handlingStrategy":"validation","validationCode":"// sum endpoint buffer needs before allocating\nconst USBRAM_SIZE: usize = 1024; // check your part\nlet needed: usize = eps.iter().map(|e| (e.in_size + e.out_size) as usize).sum();\nassert!(needed <= USBRAM_SIZE, \"USB RAM budget {} exceeds {}\", needed, USBRAM_SIZE);","typeGuard":"fn fits_usbram(total: usize, usbram: usize) -> bool { total <= usbram }","tryCatchPattern":null,"preventionTips":["Budget USBRAM per interface before adding endpoints","Prefer 64-byte FS bulk buffers unless bandwidth demands more","Check USBRAM_SIZE for your exact chip (512 B to 4 KB) in the datasheet","Recount the budget whenever adding an interface (CDC, MSC, vendor)"],"tags":["embedded","stm32","usb","memory","endpoint","panic"],"backgroundTag":"usb-endpoint-memory-full","analyzedSha":"463a07b963419a1bfe61d5d597c44acb810afb8b","analyzedAt":"2026-09-10T13:38:26.660Z","contentChangedAt":"2026-09-10T13:38:26.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}